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

📄 emit-rtl.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    return 0;  if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)    word = ((GET_MODE_SIZE (GET_MODE (x))	     - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))	    / UNITS_PER_WORD);  if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)      && (GET_MODE_CLASS (mode) == MODE_INT	  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT))    {      /* If we are getting the low-order part of something that has been	 sign- or zero-extended, we can either just use the object being	 extended or make a narrower extension.  If we want an even smaller	 piece than the size of the object being extended, call ourselves	 recursively.	 This case is used mostly by combine and cse.  */      if (GET_MODE (XEXP (x, 0)) == mode)	return XEXP (x, 0);      else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))	return gen_lowpart_common (mode, XEXP (x, 0));      else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))	return gen_rtx (GET_CODE (x), mode, XEXP (x, 0));    }  else if (GET_CODE (x) == SUBREG	   && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD	       || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))    return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0	    ? SUBREG_REG (x)	    : gen_rtx (SUBREG, mode, SUBREG_REG (x), SUBREG_WORD (x)));  else if (GET_CODE (x) == REG)    {      /* If the register is not valid for MODE, return 0.  If we don't	 do this, there is no way to fix up the resulting REG later.  */      if (REGNO (x) < FIRST_PSEUDO_REGISTER	  && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode))	return 0;      else if (REGNO (x) < FIRST_PSEUDO_REGISTER	       /* integrate.c can't handle parts of a return value register. */	       && (! REG_FUNCTION_VALUE_P (x)		   || ! rtx_equal_function_value_matters)	       /* We want to keep the stack, frame, and arg pointers		  special.  */	       && REGNO (x) != FRAME_POINTER_REGNUM#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM	       && REGNO (x) != ARG_POINTER_REGNUM#endif	       && REGNO (x) != STACK_POINTER_REGNUM)	return gen_rtx (REG, mode, REGNO (x) + word);      else	return gen_rtx (SUBREG, mode, x, word);    }  /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits     from the low-order part of the constant.  */  else if ((GET_MODE_CLASS (mode) == MODE_INT	    || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)	   && GET_MODE (x) == VOIDmode	   && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))    {      /* If MODE is twice the host word size, X is already the desired	 representation.  Otherwise, if MODE is wider than a word, we can't	 do this.  If MODE is exactly a word, return just one CONST_INT.	 If MODE is smaller than a word, clear the bits that don't belong	 in our mode, unless they and our sign bit are all one.  So we get	 either a reasonable negative value or a reasonable unsigned value	 for this mode.  */      if (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT)	return x;      else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)	return 0;      else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)	return (GET_CODE (x) == CONST_INT ? x		: GEN_INT (CONST_DOUBLE_LOW (x)));      else	{	  /* MODE must be narrower than HOST_BITS_PER_INT.  */	  int width = GET_MODE_BITSIZE (mode);	  HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x)			       : CONST_DOUBLE_LOW (x));	  if (((val & ((HOST_WIDE_INT) (-1) << (width - 1)))	       != ((HOST_WIDE_INT) (-1) << (width - 1))))	    val &= ((HOST_WIDE_INT) 1 << width) - 1;	  return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x		  : GEN_INT (val));	}    }  /* If X is an integral constant but we want it in floating-point, it     must be the case that we have a union of an integer and a floating-point     value.  If the machine-parameters allow it, simulate that union here     and return the result.  The two-word and single-word cases are      different.  */  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && GET_MODE_CLASS (mode) == MODE_FLOAT	   && GET_MODE_SIZE (mode) == UNITS_PER_WORD	   && GET_CODE (x) == CONST_INT	   && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT)    {      union {HOST_WIDE_INT i; float d; } u;      u.i = INTVAL (x);      return immed_real_const_1 (u.d, mode);    }  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && GET_MODE_CLASS (mode) == MODE_FLOAT	   && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD	   && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)	   && GET_MODE (x) == VOIDmode	   && (sizeof (double) * HOST_BITS_PER_CHAR	       == 2 * HOST_BITS_PER_WIDE_INT))    {      union {HOST_WIDE_INT i[2]; double d; } u;      HOST_WIDE_INT low, high;      if (GET_CODE (x) == CONST_INT)	low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);      else	low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);#ifdef HOST_WORDS_BIG_ENDIAN      u.i[0] = high, u.i[1] = low;#else      u.i[0] = low, u.i[1] = high;#endif      return immed_real_const_1 (u.d, mode);    }  /* Similarly, if this is converting a floating-point value into a     single-word integer.  Only do this is the host and target parameters are     compatible.  */  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && (GET_MODE_CLASS (mode) == MODE_INT	       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)	   && GET_CODE (x) == CONST_DOUBLE	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT	   && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)    return operand_subword (x, 0, 0, GET_MODE (x));  /* Similarly, if this is converting a floating-point value into a     two-word integer, we can do this one word at a time and make an     integer.  Only do this is the host and target parameters are     compatible.  */  else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	     && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)	    || flag_pretend_float)	   && (GET_MODE_CLASS (mode) == MODE_INT	       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)	   && GET_CODE (x) == CONST_DOUBLE	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT	   && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)    {      rtx lowpart = operand_subword (x, WORDS_BIG_ENDIAN, 0, GET_MODE (x));      rtx highpart = operand_subword (x, ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));      if (lowpart && GET_CODE (lowpart) == CONST_INT	  && highpart && GET_CODE (highpart) == CONST_INT)	return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);    }  /* Otherwise, we can't do this.  */  return 0;}/* Return the real part (which has mode MODE) of a complex value X.   This always comes at the low address in memory.  */rtxgen_realpart (mode, x)     enum machine_mode mode;     register rtx x;{  if (WORDS_BIG_ENDIAN)    return gen_highpart (mode, x);  else    return gen_lowpart (mode, x);}/* Return the imaginary part (which has mode MODE) of a complex value X.   This always comes at the high address in memory.  */rtxgen_imagpart (mode, x)     enum machine_mode mode;     register rtx x;{  if (WORDS_BIG_ENDIAN)    return gen_lowpart (mode, x);  else    return gen_highpart (mode, x);}/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value,   return an rtx (MEM, SUBREG, or CONST_INT) that refers to the   least-significant part of X.   MODE specifies how big a part of X to return;   it usually should not be larger than a word.   If X is a MEM whose address is a QUEUED, the value may be so also.  */rtxgen_lowpart (mode, x)     enum machine_mode mode;     register rtx x;{  rtx result = gen_lowpart_common (mode, x);  if (result)    return result;  else if (GET_CODE (x) == MEM)    {      /* The only additional case we can do is MEM.  */      register int offset = 0;      if (WORDS_BIG_ENDIAN)	offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)		  - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));      if (BYTES_BIG_ENDIAN)	/* Adjust the address so that the address-after-the-data	   is unchanged.  */	offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))		   - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));      return change_address (x, mode, plus_constant (XEXP (x, 0), offset));    }  else    abort ();}/* Like `gen_lowpart', but refer to the most significant part.    This is used to access the imaginary part of a complex number.  */rtxgen_highpart (mode, x)     enum machine_mode mode;     register rtx x;{  /* This case loses if X is a subreg.  To catch bugs early,     complain if an invalid MODE is used even in other cases.  */  if (GET_MODE_SIZE (mode) > UNITS_PER_WORD      && GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))    abort ();  if (GET_CODE (x) == CONST_DOUBLE#if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined(REAL_IS_NOT_DOUBLE))      && GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT#endif      )    return gen_rtx (CONST_INT, VOIDmode,		    CONST_DOUBLE_HIGH (x) & GET_MODE_MASK (mode));  else if (GET_CODE (x) == CONST_INT)    return const0_rtx;  else if (GET_CODE (x) == MEM)    {      register int offset = 0;#if !WORDS_BIG_ENDIAN      offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)		- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));#endif#if !BYTES_BIG_ENDIAN      if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)	offset -= (GET_MODE_SIZE (mode)		   - MIN (UNITS_PER_WORD,			  GET_MODE_SIZE (GET_MODE (x))));#endif      return change_address (x, mode, plus_constant (XEXP (x, 0), offset));    }  else if (GET_CODE (x) == SUBREG)    {      /* The only time this should occur is when we are looking at a	 multi-word item with a SUBREG whose mode is the same as that of the	 item.  It isn't clear what we would do if it wasn't.  */      if (SUBREG_WORD (x) != 0)	abort ();      return gen_highpart (mode, SUBREG_REG (x));    }  else if (GET_CODE (x) == REG)    {      int word = 0;#if !WORDS_BIG_ENDIAN      if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)	word = ((GET_MODE_SIZE (GET_MODE (x))		 - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))		/ UNITS_PER_WORD);#endif      if (REGNO (x) < FIRST_PSEUDO_REGISTER	  /* We want to keep the stack, frame, and arg pointers special.  */	  && REGNO (x) != FRAME_POINTER_REGNUM#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM	  && REGNO (x) != ARG_POINTER_REGNUM#endif	  && REGNO (x) != STACK_POINTER_REGNUM)	return gen_rtx (REG, mode, REGNO (x) + word);      else	return gen_rtx (SUBREG, mode, x, word);    }  else    abort ();}/* Return 1 iff X, assumed to be a SUBREG,   refers to the least significant part of its containing reg.   If X is not a SUBREG, always return 1 (it is its own low part!).  */intsubreg_lowpart_p (x)     rtx x;{  if (GET_CODE (x) != SUBREG)    return 1;  if (WORDS_BIG_ENDIAN      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)    return (SUBREG_WORD (x)	    == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))		 - MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))		/ UNITS_PER_WORD));  return SUBREG_WORD (x) == 0;}/* Return subword I of operand OP.   The word number, I, is interpreted as the word number starting at the   low-order address.  Word 0 is the low-order word if not WORDS_BIG_ENDIAN,   otherwise it is the high-order word.   If we cannot extract the required word, we return zero.  Otherwise, an   rtx corresponding to the requested word will be returned.   VALIDATE_ADDRESS is nonzero if the address should be validated.  Before   reload has completed, a valid address will always be returned.  After   reload, if a valid address cannot be returned, we return zero.   If VALIDATE_ADDRESS is zero, we simply form the required address; validating   it is the responsibility of the caller.   MODE is the mode of OP in case it is a CONST_INT.  */rtxoperand_subword (op, i, validate_address, mode)     rtx op;     int i;     int validate_address;     enum machine_mode mode;{  HOST_WIDE_INT val;  int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;  if (mode == VOIDmode)    mode = GET_MODE (op);  if (mode == VOIDmode)    abort ();  /* If OP is narrower than a word or if we want a word outside OP, fail.  */  if (mode != BLKmode      && (GET_MODE_SIZE (mode) < UNITS_PER_WORD	  || (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode)))    return 0;  /* If OP is already an integer word, return it.  */  if (GET_MODE_CLASS (mode) == MODE_INT      && GET_MODE_SIZE (mode) == UNITS_PER_WORD)    return op;  /* If OP is a REG or SUBREG, we can handle it very simply.  */  if (GET_CODE (op) == REG)    {      /* If the register is not valid for MODE, return 0.  If we don't	 do this, there is no way to fix up the resulting REG later.  */      if (REGNO (op) < FIRST_PSEUDO_REGISTER	  && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode))	return 0;      else if (REGNO (op) >= FIRST_PSEUDO_REGISTER	       || (REG_FUNCTION_VALUE_P (op)		   && rtx_equal_function_value_matters)	       /* We want to keep the stack, frame, and arg pointers		  special.  */	       || REGNO (op) == FRAME_POINTER_REGNUM#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM	       || REGNO (op) == ARG_POINTER_REGNUM#endif	       || REGNO (op) == STACK_POINTER_REGNUM)	return gen_rtx (SUBREG, word_mode, op, i);      else	return gen_rtx (REG, word_mode, REGNO (op) + i);    }  else if (GET_CODE (op) == SUBREG)    return gen_rtx (SUBREG, word_mode, SUBREG_REG (op), i + SUBREG_WORD (op));  /* Form a new MEM at the requested address.  */  if (GET_CODE (op) == MEM)    {      rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD);      rtx new;      if (validate_address)	{	  if (reload_completed)	    {	      if (! strict_memory_address_p (word_mode, addr))		return 0;	    }	  else	    addr = memory_address (word_mode, addr);	}      new = gen_rtx (MEM, word_mode, addr);      MEM_VOLATILE_P (new) = MEM_VOLATILE_P (op);      MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (op);      RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);      return new;    }  /* The only remaining cases are when OP is a constant.  If the host and     target floating formats are the same, handling two-word floating     constants are easy.  */  if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)       || flag_pretend_float)      && GET_MODE_CLASS (mode) == MODE_FLOAT      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD      && GET_CODE (op) == CONST_DOUBLE)    {      /* The constant is stored in the host's word-ordering,	 but we want to access it in the target's word-ordering.  Some	 compilers don't like a conditional inside macro args, so we have two	 copies of the return.  */#ifdef HOST_WORDS_BIG_ENDIAN      return GEN_INT (i == WORDS_BIG_ENDIAN		      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));#else      return GEN_INT (i != WORDS_BIG_ENDIAN		      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));#endif    }  /* Single word float is a little harder, since single- and double-word     values often do not have the same high-order bits.  We have already     verified that we want the only defined word of the single-word value.  */  if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)       || flag_pretend_float)      && GET_MODE_CLASS (mode) == MODE_FLOAT      && GET_MODE_SIZE (mode) == UNITS_PER_WORD      && GET_CODE (op) == CONST_DOUBLE)    {      double d;      union {float f; HOST_WIDE_INT i; } u;      REAL_VALUE_FROM_CONST_DOUBLE (d, op);      u.f = d;      return GEN_INT (u.i);    }        /* The only remaining cases that we can handle are integers.     Convert to proper endianness now since these cases need it.     At this point, i == 0 means the low-order word.       Note that it must be that BITS_PER_WORD <= HOST_BITS_PER_INT.     This is because if it were greater, it could only have been two     times greater since we do not support making wider constants.  In     that case, it MODE would have already been the proper size and     it would have been handled above.  This means we do not have to     worry about the case where we would be returning a CONST_DOUBLE.  */  if (GET_MODE_CLASS (mode) != MODE_INT      || (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE))    return 0;  if (WORDS_BIG_ENDIAN)    i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;

⌨️ 快捷键说明

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