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

📄 expmed.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
		     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 extv_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));	    }	  /* If op0 is a register, we need it in MAXMODE (which is usually	     SImode) to make it acceptable to the format of extv.  */	  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;	  /* XBITPOS counts within a size of UNIT.	     Adjust to count within a size of 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 extv insists on a register target,	     make sure we have one.  */	  if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][0])		 (xtarget, maxmode)))	    xtarget = gen_reg_rtx (maxmode);	  bitsize_rtx = GEN_INT (bitsize);	  bitpos_rtx = GEN_INT (xbitpos);	  pat = gen_extv (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, 0, align);	    }	}       else	extv_loses:#endif	target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,					  target, 0, align);    }  if (target == spec_target)    return target;  if (target == spec_target_subreg)    return spec_target;  if (GET_MODE (target) != tmode && GET_MODE (target) != mode)    {      /* If the target mode is floating-point, first convert to the	 integer mode of that size and then access it as a floating-point	 value via a SUBREG.  */      if (GET_MODE_CLASS (tmode) == MODE_FLOAT)	{	  target = convert_to_mode (mode_for_size (GET_MODE_BITSIZE (tmode),						   MODE_INT, 0),				    target, unsignedp);	  if (GET_CODE (target) != REG)	    target = copy_to_reg (target);	  return gen_rtx (SUBREG, tmode, target, 0);	}      else	return convert_to_mode (tmode, target, unsignedp);    }  return target;}/* Extract a bit field using shifts and boolean operations   Returns an rtx to represent the value.   OP0 addresses a register (word) or memory (byte).   BITPOS says which bit within the word or byte the bit field starts in.   OFFSET says how many bytes farther the bit field starts;    it is 0 if OP0 is a register.   BITSIZE says how many bits long the bit field is.    (If OP0 is a register, it may be narrower than a full word,     but BITPOS still counts within a full word,     which is significant on bigendian machines.)   UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).   If TARGET is nonzero, attempts to store the value there   and return TARGET, but this is not guaranteed.   If TARGET is not used, create a pseudo-reg of mode TMODE for the value.   ALIGN is the alignment that STR_RTX is known to have, measured in bytes.  */static rtxextract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,			 target, unsignedp, align)     enum machine_mode tmode;     register rtx op0, target;     register int offset, bitsize, bitpos;     int unsignedp;     int align;{  int total_bits = BITS_PER_WORD;  enum machine_mode mode;  if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)    {      /* Special treatment for a bit field split across two registers.  */      if (bitsize + bitpos > BITS_PER_WORD)	return extract_split_bit_field (op0, bitsize, bitpos,					unsignedp, align);    }  else    {      /* Get the proper mode to use for this field.  We want a mode that	 includes the entire field.  If such a mode would be larger than	 a word, we won't be doing the extraction the normal way.  */      mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,			    align * BITS_PER_UNIT, word_mode,			    GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));      if (mode == VOIDmode)	/* The only way this should occur is if the field spans word	   boundaries.  */	return extract_split_bit_field (op0, bitsize,					bitpos + offset * BITS_PER_UNIT,					unsignedp, align);      total_bits = GET_MODE_BITSIZE (mode);      /* Make sure bitpos is valid for the chosen mode.  Adjust BITPOS to	 be be in the range 0 to total_bits-1, and put any excess bytes in	 OFFSET.  */      if (bitpos >= total_bits)	{	  offset += (bitpos / total_bits) * (total_bits / BITS_PER_UNIT);	  bitpos -= ((bitpos / total_bits) * (total_bits / BITS_PER_UNIT)		     * BITS_PER_UNIT);	}      /* Get ref to an aligned byte, halfword, or word containing the field.	 Adjust BITPOS to be position within a word,	 and OFFSET to be the offset of that word.	 Then alter OP0 to refer to that word.  */      bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;      offset -= (offset % (total_bits / BITS_PER_UNIT));      op0 = change_address (op0, mode,			    plus_constant (XEXP (op0, 0), offset));    }  mode = GET_MODE (op0);  if (BYTES_BIG_ENDIAN)    {      /* BITPOS is the distance between our msb and that of OP0.	 Convert it to the distance from the lsb.  */      bitpos = total_bits - bitsize - bitpos;    }  /* Now BITPOS is always the distance between the field's lsb and that of OP0.     We have reduced the big-endian case to the little-endian case.  */  if (unsignedp)    {      if (bitpos)	{	  /* If the field does not already start at the lsb,	     shift it so it does.  */	  tree amount = build_int_2 (bitpos, 0);	  /* Maybe propagate the target for the shift.  */	  /* But not if we will return it--could confuse integrate.c.  */	  rtx subtarget = (target != 0 && GET_CODE (target) == REG			   && !REG_FUNCTION_VALUE_P (target)			   ? target : 0);	  if (tmode != mode) subtarget = 0;	  op0 = expand_shift (RSHIFT_EXPR, mode, op0, amount, subtarget, 1);	}      /* Convert the value to the desired mode.  */      if (mode != tmode)	op0 = convert_to_mode (tmode, op0, 1);      /* Unless the msb of the field used to be the msb when we shifted,	 mask out the upper bits.  */      if (GET_MODE_BITSIZE (mode) != bitpos + bitsize#if 0#ifdef SLOW_ZERO_EXTEND	  /* Always generate an `and' if	     we just zero-extended op0 and SLOW_ZERO_EXTEND, since it	     will combine fruitfully with the zero-extend. */	  || tmode != mode#endif#endif	  )	return expand_binop (GET_MODE (op0), and_optab, op0,			     mask_rtx (GET_MODE (op0), 0, bitsize, 0),			     target, 1, OPTAB_LIB_WIDEN);      return op0;    }  /* To extract a signed bit-field, first shift its msb to the msb of the word,     then arithmetic-shift its lsb to the lsb of the word.  */  op0 = force_reg (mode, op0);  if (mode != tmode)    target = 0;  /* Find the narrowest integer mode that contains the field.  */  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;       mode = GET_MODE_WIDER_MODE (mode))    if (GET_MODE_BITSIZE (mode) >= bitsize + bitpos)      {	op0 = convert_to_mode (mode, op0, 0);	break;      }  if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos))    {      tree amount = build_int_2 (GET_MODE_BITSIZE (mode) - (bitsize + bitpos), 0);      /* Maybe propagate the target for the shift.  */      /* But not if we will return the result--could confuse integrate.c.  */      rtx subtarget = (target != 0 && GET_CODE (target) == REG		       && ! REG_FUNCTION_VALUE_P (target)		       ? target : 0);      op0 = expand_shift (LSHIFT_EXPR, mode, op0, amount, subtarget, 1);    }  return expand_shift (RSHIFT_EXPR, mode, op0,		       build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0), 		       target, 0);}/* Return a constant integer (CONST_INT or CONST_DOUBLE) mask value   of mode MODE with BITSIZE ones followed by BITPOS zeros, or the   complement of that if COMPLEMENT.  The mask is truncated if   necessary to the width of mode MODE.  The mask is zero-extended if   BITSIZE+BITPOS is too small for MODE.  */static rtxmask_rtx (mode, bitpos, bitsize, complement)     enum machine_mode mode;     int bitpos, bitsize, complement;{  HOST_WIDE_INT masklow, maskhigh;  if (bitpos < HOST_BITS_PER_WIDE_INT)    masklow = (HOST_WIDE_INT) -1 << bitpos;  else    masklow = 0;  if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT)    masklow &= ((unsigned HOST_WIDE_INT) -1		>> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize));    if (bitpos <= HOST_BITS_PER_WIDE_INT)    maskhigh = -1;  else    maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT);  if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT)    maskhigh &= ((unsigned HOST_WIDE_INT) -1		 >> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize));  else    maskhigh = 0;  if (complement)    {      maskhigh = ~maskhigh;      masklow = ~masklow;    }  return immed_double_const (masklow, maskhigh, mode);}/* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value   VALUE truncated to BITSIZE bits and then shifted left BITPOS bits.  */static rtxlshift_value (mode, value, bitpos, bitsize)     enum machine_mode mode;     rtx value;     int bitpos, bitsize;{  unsigned HOST_WIDE_INT v = INTVAL (value);  HOST_WIDE_INT low, high;  if (bitsize < HOST_BITS_PER_WIDE_INT)    v &= ~((HOST_WIDE_INT) -1 << bitsize);  if (bitpos < HOST_BITS_PER_WIDE_INT)    {      low = v << bitpos;      high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0);    }  else    {      low = 0;      high = v << (bitpos - HOST_BITS_PER_WIDE_INT);    }  return immed_double_const (low, high, mode);}/* Extract a bit field that is split across two words   and return an RTX for the result.   OP0 is the REG, SUBREG or MEM rtx for the first of the two words.   BITSIZE is the field width; BITPOS, position of its first bit, in the word.   UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend.   ALIGN is the known alignment of OP0, measured in bytes.   This is also the size of the memory objects to be used.  */static rtxextract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)     rtx op0;     int bitsize, bitpos, unsignedp, align;{  int unit;  int bitsdone = 0;  rtx result;  int first = 1;  /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that     much at a time.  */  if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)    unit = BITS_PER_WORD;  else    unit = MIN (align * BITS_PER_UNIT, BITS_PER_WORD);  while (bitsdone < bitsize)    {      int thissize;      rtx part, word;      int thispos;      int offset;      offset = (bitpos + bitsdone) / unit;      thispos = (bitpos + bitsdone) % unit;      /* THISSIZE must not overrun a word boundary.  Otherwise,	 extract_fixed_bit_field will call us again, and we will mutually	 recurse forever.  */      thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);      thissize = MIN (thissize, unit - thispos);      /* If OP0 is a register, then handle OFFSET here.	 When handling multiword bitfields, extract_bit_field may pass	 down a word_mode SUBREG of a larger REG for a bitfield that actually

⌨️ 快捷键说明

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