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

📄 expmed.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	 crosses a word boundary.  Thus, for a SUBREG, we must find	 the current word starting from the base register.  */      if (GET_CODE (op0) == SUBREG)	{	  word = operand_subword_force (SUBREG_REG (op0),					SUBREG_WORD (op0) + offset,					GET_MODE (SUBREG_REG (op0)));	  offset = 0;	}      else if (GET_CODE (op0) == REG)	{	  word = operand_subword_force (op0, offset, GET_MODE (op0));	  offset = 0;	}      else	word = op0;      /* OFFSET is in UNITs, and UNIT is in bits.         store_fixed_bit_field wants offset in bytes.  */      store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT,			     thissize, thispos, part, align);      bitsdone += thissize;    }}/* Generate code to extract a byte-field from STR_RTX   containing BITSIZE bits, starting at BITNUM,   and put it in TARGET if possible (if TARGET is nonzero).   Regardless of TARGET, we return the rtx for where the value is placed.   It may be a QUEUED.   STR_RTX is the structure containing the byte (a REG or MEM).   UNSIGNEDP is nonzero if this is an unsigned bit field.   MODE is the natural mode of the field value once extracted.   TMODE is the mode the caller would like the value to have;   but the value may be returned with type MODE instead.   ALIGN is the alignment that STR_RTX is known to have, measured in bytes.   TOTAL_SIZE is the size in bytes of the containing structure,   or -1 if varying.   If a TARGET is specified and we can store in it at no extra cost,   we do so, and return TARGET.   Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred   if they are equally easy.  */rtxextract_bit_field (str_rtx, bitsize, bitnum, unsignedp,		   target, mode, tmode, align, total_size)     rtx str_rtx;     register int bitsize;     int bitnum;     int unsignedp;     rtx target;     enum machine_mode mode, tmode;     int align;     int total_size;{  int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;  register int offset = bitnum / unit;  register int bitpos = bitnum % unit;  register rtx op0 = str_rtx;  rtx spec_target = target;  rtx spec_target_subreg = 0;  if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx))    abort ();  /* Discount the part of the structure before the desired byte.     We need to know how many bytes are safe to reference after it.  */  if (total_size >= 0)    total_size -= (bitpos / BIGGEST_ALIGNMENT		   * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));  if (tmode == VOIDmode)    tmode = mode;  while (GET_CODE (op0) == SUBREG)    {      int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));      int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));      offset += SUBREG_WORD (op0);      if (BYTES_BIG_ENDIAN && (outer_size < inner_size))	{	  bitpos += inner_size - outer_size;	  if (bitpos > unit)	    {	      offset += (bitpos / unit);	      bitpos %= unit;	    }	}      op0 = SUBREG_REG (op0);    }  /* ??? We currently assume TARGET is at least as big as BITSIZE.     If that's wrong, the solution is to test for it and set TARGET to 0     if needed.  */    /* If OP0 is a register, BITPOS must count within a word.     But as we have it, it counts within whatever size OP0 now has.     On a bigendian machine, these are not the same, so convert.  */  if (BYTES_BIG_ENDIAN &&      GET_CODE (op0) != MEM      && unit > GET_MODE_BITSIZE (GET_MODE (op0)))    bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));  /* Extracting a full-word or multi-word value     from a structure in a register or aligned memory.     This can be done with just SUBREG.     So too extracting a subword value in     the least significant part of the register.  */  if ((GET_CODE (op0) == REG       || (GET_CODE (op0) == MEM	   && (! SLOW_UNALIGNED_ACCESS	       || (offset * BITS_PER_UNIT % bitsize == 0		   && align * BITS_PER_UNIT % bitsize == 0))))      && ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)	   && bitpos % BITS_PER_WORD == 0)	  || (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode	      && (BYTES_BIG_ENDIAN		  ? bitpos + bitsize == BITS_PER_WORD		  : bitpos == 0))))    {      enum machine_mode mode1	= mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0);      if (mode1 != GET_MODE (op0))	{	  if (GET_CODE (op0) == REG)	    op0 = gen_rtx (SUBREG, mode1, op0, offset);	  else	    op0 = change_address (op0, mode1,				  plus_constant (XEXP (op0, 0), offset));	}      if (mode1 != mode)	return convert_to_mode (tmode, op0, unsignedp);      return op0;    }  /* Handle fields bigger than a word.  */    if (bitsize > BITS_PER_WORD)    {      /* Here we transfer the words of the field	 in the order least significant first.	 This is because the most significant word is the one which may	 be less than full.  */      int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;      int i;      if (target == 0 || GET_CODE (target) != REG)	target = gen_reg_rtx (mode);      for (i = 0; i < nwords; i++)	{	  /* If I is 0, use the low-order word in both field and target;	     if I is 1, use the next to lowest word; and so on.  */	  /* Word number in TARGET to use.  */	  int wordnum = (WORDS_BIG_ENDIAN			 ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1			 : i);	  /* Offset from start of field in OP0.  */	  int bit_offset = (WORDS_BIG_ENDIAN			    ? MAX (0, bitsize - (i + 1) * BITS_PER_WORD)			    : i * BITS_PER_WORD);	  rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);	  rtx result_part	    = extract_bit_field (op0, MIN (BITS_PER_WORD,					   bitsize - i * BITS_PER_WORD),				 bitnum + bit_offset,				 1, target_part, mode, word_mode,				 align, total_size);	  if (target_part == 0)	    abort ();	  if (result_part != target_part)	    emit_move_insn (target_part, result_part);	}      if (unsignedp)	{	  /* Unless we've filled TARGET, the upper regs in a multi-reg value	     need to be zero'd out.  */	  if (GET_MODE_SIZE (GET_MODE (target)) > nwords * UNITS_PER_WORD)	    {	      int i,total_words;	      total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD;	      for (i = nwords; i < total_words; i++)		{		  int wordnum = WORDS_BIG_ENDIAN ? total_words - i - 1 : i;		  rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);		  emit_move_insn (target_part, const0_rtx);		}	    }	  return target;	}      /* Signed bit field: sign-extend with two arithmetic shifts.  */      target = expand_shift (LSHIFT_EXPR, mode, target,			     build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0),			     NULL_RTX, 0);      return expand_shift (RSHIFT_EXPR, mode, target,			   build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0),			   NULL_RTX, 0);    }    /* From here on we know the desired field is smaller than a word     so we can assume it is an integer.  So we can safely extract it as one     size of integer, if necessary, and then truncate or extend     to the size that is wanted.  */  /* OFFSET is the number of words or bytes (UNIT says which)     from STR_RTX to the first word or byte containing part of the field.  */  if (GET_CODE (op0) == REG)    {      if (offset != 0	  || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)	op0 = gen_rtx (SUBREG, TYPE_MODE (type_for_size (BITS_PER_WORD, 0)),		       op0, offset);      offset = 0;    }  else    {      op0 = protect_from_queue (str_rtx, 1);    }  /* Now OFFSET is nonzero only for memory operands.  */  if (unsignedp)    {#ifdef HAVE_extzv      if (HAVE_extzv	  && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0])	      >= bitsize)	  && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)		&& (bitsize + bitpos		    > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]))))	{	  int xbitpos = bitpos, xoffset = offset;	  rtx bitsize_rtx, bitpos_rtx;	  rtx last = get_last_insn();	  rtx xop0 = op0;	  rtx xtarget = target;	  rtx xspec_target = spec_target;	  rtx xspec_target_subreg = spec_target_subreg;	  rtx pat;	  enum machine_mode maxmode	    = insn_operand_mode[(int) CODE_FOR_extzv][0];	  if (GET_CODE (xop0) == MEM)	    {	      int save_volatile_ok = volatile_ok;	      volatile_ok = 1;	      /* Is the memory operand acceptable?  */	      if (flag_force_mem		  || ! ((*insn_operand_predicate[(int) CODE_FOR_extzv][1])			(xop0, GET_MODE (xop0))))		{		  /* No, load into a reg and extract from there.  */		  enum machine_mode bestmode;		  /* Get the mode to use for inserting into this field.  If		     OP0 is BLKmode, get the smallest mode consistent with the		     alignment. If OP0 is a non-BLKmode object that is no		     wider than MAXMODE, use its mode. Otherwise, use the		     smallest mode containing the field.  */		  if (GET_MODE (xop0) == BLKmode		      || (GET_MODE_SIZE (GET_MODE (op0))			  > GET_MODE_SIZE (maxmode)))		    bestmode = get_best_mode (bitsize, bitnum,					      align * BITS_PER_UNIT, maxmode,					      MEM_VOLATILE_P (xop0));		  else		    bestmode = GET_MODE (xop0);		  if (bestmode == VOIDmode		      || (SLOW_UNALIGNED_ACCESS && GET_MODE_SIZE (bestmode) > align))		    goto extzv_loses;		  /* Compute offset as multiple of this unit,		     counting in bytes.  */		  unit = GET_MODE_BITSIZE (bestmode);		  xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);		  xbitpos = bitnum % unit;		  xop0 = change_address (xop0, bestmode,					 plus_constant (XEXP (xop0, 0),							xoffset));		  /* Fetch it to a register in that size.  */		  xop0 = force_reg (bestmode, xop0);		  /* XBITPOS counts within UNIT, which is what is expected.  */		}	      else		/* Get ref to first byte containing part of the field.  */		xop0 = change_address (xop0, byte_mode,				       plus_constant (XEXP (xop0, 0), xoffset));	      volatile_ok = save_volatile_ok;	    }	  /* If op0 is a register, we need it in MAXMODE (which is usually	     SImode). to make it acceptable to the format of extzv.  */	  if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode)	    abort ();	  if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)	    xop0 = gen_rtx (SUBREG, maxmode, xop0, 0);	  /* On big-endian machines, we count bits from the most significant.	     If the bit field insn does not, we must invert.  */	  if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)	    xbitpos = unit - bitsize - xbitpos;	  /* Now convert from counting within UNIT to counting in MAXMODE.  */	  if (BITS_BIG_ENDIAN && GET_CODE (xop0) != MEM)	    xbitpos += GET_MODE_BITSIZE (maxmode) - unit;	  unit = GET_MODE_BITSIZE (maxmode);	  if (xtarget == 0	      || (flag_force_mem && GET_CODE (xtarget) == MEM))	    xtarget = xspec_target = gen_reg_rtx (tmode);	  if (GET_MODE (xtarget) != maxmode)	    {	      if (GET_CODE (xtarget) == REG)		{		  int wider = (GET_MODE_SIZE (maxmode)			       > GET_MODE_SIZE (GET_MODE (xtarget)));		  xtarget = gen_lowpart (maxmode, xtarget);		  if (wider)		    xspec_target_subreg = xtarget;		}	      else		xtarget = gen_reg_rtx (maxmode);	    }	  /* If this machine's extzv insists on a register target,	     make sure we have one.  */	  if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][0])		 (xtarget, maxmode)))	    xtarget = gen_reg_rtx (maxmode);	  bitsize_rtx = GEN_INT (bitsize);	  bitpos_rtx = GEN_INT (xbitpos);	  pat = gen_extzv (protect_from_queue (xtarget, 1),			   xop0, bitsize_rtx, bitpos_rtx);	  if (pat)	    {	      emit_insn (pat);	      target = xtarget;	      spec_target = xspec_target;	      spec_target_subreg = xspec_target_subreg;	    }	  else	    {	      delete_insns_since (last);	      target = extract_fixed_bit_field (tmode, op0, offset, bitsize,						bitpos, target, 1, align);	    }	}      else        extzv_loses:#endif	target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,					  target, 1, align);    }  else    {#ifdef HAVE_extv      if (HAVE_extv	  && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0])	      >= bitsize)	  && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)		&& (bitsize + bitpos		    > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]))))	{	  int xbitpos = bitpos, xoffset = offset;	  rtx bitsize_rtx, bitpos_rtx;	  rtx last = get_last_insn();	  rtx xop0 = op0, xtarget = target;	  rtx xspec_target = spec_target;	  rtx xspec_target_subreg = spec_target_subreg;	  rtx pat;	  enum machine_mode maxmode	    = insn_operand_mode[(int) CODE_FOR_extv][0];	  if (GET_CODE (xop0) == MEM)	    {	      /* Is the memory operand acceptable?  */	      if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][1])		     (xop0, GET_MODE (xop0))))		{		  /* No, load into a reg and extract from there.  */		  enum machine_mode bestmode;		  /* Get the mode to use for inserting into this field.  If

⌨️ 快捷键说明

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