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

📄 emit-rtl.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  return SUBREG_WORD (x) == 0;}/* 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) == REG)    {      /* Must be a hard reg that's not valid in MODE.  */      result = gen_lowpart_common (mode, copy_to_reg (x));      if (result == 0)	abort ();      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 if (GET_CODE (x) == ADDRESSOF)    return gen_lowpart (mode, force_reg (GET_MODE (x), x));  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));      if (! BYTES_BIG_ENDIAN	  && GET_MODE_SIZE (mode) < UNITS_PER_WORD)	offset -= (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 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	  && 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);      /*       * ??? This fails miserably for complex values being passed in registers       * where the sizeof the real and imaginary part are not equal to the       * sizeof SImode.  FIXME       */      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.  */	  && x != frame_pointer_rtx#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM	  && x != arg_pointer_rtx#endif	  && x != stack_pointer_rtx)	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;  else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)    return 0;  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.  */	       || op == frame_pointer_rtx#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM	       || op == arg_pointer_rtx#endif	       || op == stack_pointer_rtx)	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));  else if (GET_CODE (op) == CONCAT)    {      int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;      if (i < partwords)	return operand_subword (XEXP (op, 0), i, validate_address, mode);      return operand_subword (XEXP (op, 1), i - partwords,			      validate_address, mode);    }  /* 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.  Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}     are defined as returning one or two 32 bit values, respectively,     and not values of BITS_PER_WORD bits.  */#ifdef REAL_ARITHMETIC/*  The output is some bits, the width of the target machine's word.    A wider-word host can surely hold them in a CONST_INT. A narrower-word    host can't.  */  if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD      && GET_MODE_CLASS (mode) == MODE_FLOAT      && GET_MODE_BITSIZE (mode) == 64      && GET_CODE (op) == CONST_DOUBLE)    {      long k[2];      REAL_VALUE_TYPE rv;      REAL_VALUE_FROM_CONST_DOUBLE (rv, op);      REAL_VALUE_TO_TARGET_DOUBLE (rv, k);      /* We handle 32-bit and >= 64-bit words here.  Note that the order in	 which the words are written depends on the word endianness.	 ??? This is a potential portability problem and should	 be fixed at some point.  */      if (BITS_PER_WORD == 32)	return GEN_INT ((HOST_WIDE_INT) k[i]);#if HOST_BITS_PER_WIDE_INT > 32      else if (BITS_PER_WORD >= 64 && i == 0)	return GEN_INT ((((HOST_WIDE_INT) k[! WORDS_BIG_ENDIAN]) << 32)			| (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN]);#endif      else if (BITS_PER_WORD == 16)	{	  long value;	  value = k[i >> 1];	  if ((i & 0x1) == 0)	    value >>= 16;	  value &= 0xffff;	  return GEN_INT ((HOST_WIDE_INT) value);	}      else	abort ();    }  else if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD	   && GET_MODE_CLASS (mode) == MODE_FLOAT	   && GET_MODE_BITSIZE (mode) > 64	   && GET_CODE (op) == CONST_DOUBLE)  {    long k[4];    REAL_VALUE_TYPE rv;    REAL_VALUE_FROM_CONST_DOUBLE (rv, op);    REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);    if (BITS_PER_WORD == 32)      return GEN_INT ((HOST_WIDE_INT) k[i]);  }#else /* no REAL_ARITHMETIC */  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    }#endif /* no REAL_ARITHMETIC */  /* 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.  */#ifdef REAL_ARITHMETIC  if (GET_MODE_CLASS (mode) == MODE_FLOAT      && GET_MODE_BITSIZE (mode) == 32      && GET_CODE (op) == CONST_DOUBLE)    {      long l;      REAL_VALUE_TYPE rv;      REAL_VALUE_FROM_CONST_DOUBLE (rv, op);      REAL_VALUE_TO_TARGET_SINGLE (rv, l);      return GEN_INT ((HOST_WIDE_INT) l);    }#else  if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)       || flag_pretend_float)      && sizeof (float) * 8 == HOST_BITS_PER_WIDE_INT      && 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);    }  if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT	&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)       || flag_pretend_float)      && sizeof (double) * 8 == HOST_BITS_PER_WIDE_INT      && GET_MODE_CLASS (mode) == MODE_FLOAT      && GET_MODE_SIZE (mode) == UNITS_PER_WORD      && GET_CODE (op) == CONST_DOUBLE)    {      double d;      union {double d; HOST_WIDE_INT i; } u;      REAL_VALUE_FROM_CONST_DOUBLE (d, op);      u.d = d;      return GEN_INT (u.i);    }#endif /* no REAL_ARITHMETIC */        /* 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.       We do not want to handle the case when BITS_PER_WORD <= HOST_BITS_PER_INT     in general.  However, if OP is (const_int 0), we can just return     it for any word.  */  if (op == const0_rtx)    return op;  if (GET_MODE_CLASS (mode) != MODE_INT      || (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE)      || BITS_PER_WORD > HOST_BITS_PER_WIDE_INT)    return 0;  if (WORDS_BIG_ENDIAN)    i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;  /* Find out which word on the host machine this value is in and get     it from the constant.  */  val = (i / size_ratio == 0	 ? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))	 : (GET_CODE (op) == CONST_INT	    ? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));  /* If BITS_PER_WORD is smaller than an int, get the appropriate bits.  */  if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)    val = ((val >> ((i % size_ratio) * BITS_PER_WORD))	   & (((HOST_WIDE_INT) 1	       << (BITS_PER_WORD % HOST_BITS_PER_WIDE_INT)) - 1));  return GEN_INT (val);}/* Similar to `operand_subword', but never return 0.  If we can't extract   the required subword, put OP into a register and try again.  If that fails,   abort.  We always validate the address in this case.  It is not valid   to call this function after reload; it is mostly meant for RTL   generation.    MODE is the mode of OP, in case it is CONST_INT.  */rtxoperand_subword_force (op, i, mode)     rtx op;     int i;     enum machine_mode mode;{  rtx result = operand_subword (op, i, 1, mode);  if (result)    return result;  if (mode != BLKmode && mode != VOIDmode)    op = force_reg (mode, op);  result = operand_subword (op, i, 1, mode);  if (result == 0)    abort ();  return result;}/* Given a compare instruction, swap the operands.   A test instruction is changed into a compare of 0 against the operand.  */voidreverse_comparison (insn)     rtx insn;{  rtx body = PATTERN (insn);  rtx comp;

⌨️ 快捷键说明

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