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

📄 alpha.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* Return 1 if OP is a valid operand for the source of a move insn.  */intinput_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))    return 0;  if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)    return 0;  switch (GET_CODE (op))    {    case LABEL_REF:    case SYMBOL_REF:    case CONST:        /* This handles both the Windows/NT and OSF cases.  */      return mode == ptr_mode || mode == DImode;    case REG:      return 1;    case SUBREG:      if (register_operand (op, mode))	return 1;      /* ... fall through ... */    case MEM:      return ((TARGET_BWX || (mode != HImode && mode != QImode))	      && general_operand (op, mode));    case CONST_DOUBLE:      return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);    case CONST_INT:      return mode == QImode || mode == HImode || add_operand (op, mode);    }  return 0;}/* Return 1 if OP is a SYMBOL_REF for a function known to be in this   file.  */intcurrent_file_function_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == SYMBOL_REF	  && ! profile_flag && ! profile_block_flag	  && (SYMBOL_REF_FLAG (op)	      || op == XEXP (DECL_RTL (current_function_decl), 0)));}/* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */intcall_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (mode != Pmode)    return 0;  return (GET_CODE (op) == SYMBOL_REF	  || (GET_CODE (op) == REG && (TARGET_OPEN_VMS || REGNO (op) == 27)));}/* Return 1 if OP is a valid Alpha comparison operator.  Here we know which   comparisons are valid in which insn.  */intalpha_comparison_operator (op, mode)     register rtx op;     enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')    return 0;  return (code == EQ || code == LE || code == LT	  || (mode == DImode && (code == LEU || code == LTU)));}/* Return 1 if OP is a valid Alpha swapped comparison operator.  */intalpha_swapped_comparison_operator (op, mode)     register rtx op;     enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')    return 0;  code = swap_condition (code);  return (code == EQ || code == LE || code == LT	  || (mode == DImode && (code == LEU || code == LTU)));}/* Return 1 if OP is a signed comparison operation.  */intsigned_comparison_operator (op, mode)     register rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    case EQ:  case NE:  case LE:  case LT:  case GE:   case GT:      return 1;    }  return 0;}/* Return 1 if this is a divide or modulus operator.  */intdivmod_operator (op, mode)     register rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    case DIV:  case MOD:  case UDIV:  case UMOD:      return 1;    }  return 0;}/* Return 1 if this memory address is a known aligned register plus   a constant.  It must be a valid address.  This means that we can do   this as an aligned reference plus some offset.   Take into account what reload will do.   We could say that out-of-range stack slots are alignable, but that would   complicate get_aligned_mem and it isn't worth the trouble since few   functions have large stack space.  */intaligned_memory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == SUBREG)    {      if (GET_MODE (op) != mode)	return 0;      op = SUBREG_REG (op);      mode = GET_MODE (op);    }  if (reload_in_progress && GET_CODE (op) == REG      && REGNO (op) >= FIRST_PSEUDO_REGISTER)    op = reg_equiv_mem[REGNO (op)];  if (GET_CODE (op) != MEM || GET_MODE (op) != mode      || ! memory_address_p (mode, XEXP (op, 0)))    return 0;  op = XEXP (op, 0);  if (GET_CODE (op) == PLUS)    op = XEXP (op, 0);  return (GET_CODE (op) == REG	  && REGNO_POINTER_ALIGN (REGNO (op)) >= 4);}/* Similar, but return 1 if OP is a MEM which is not alignable.  */intunaligned_memory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == SUBREG)    {      if (GET_MODE (op) != mode)	return 0;      op = SUBREG_REG (op);      mode = GET_MODE (op);    }  if (reload_in_progress && GET_CODE (op) == REG      && REGNO (op) >= FIRST_PSEUDO_REGISTER)    op = reg_equiv_mem[REGNO (op)];  if (GET_CODE (op) != MEM || GET_MODE (op) != mode)    return 0;  op = XEXP (op, 0);  if (! memory_address_p (mode, op))    return 1;  if (GET_CODE (op) == PLUS)    op = XEXP (op, 0);  return (GET_CODE (op) != REG	  || REGNO_POINTER_ALIGN (REGNO (op)) < 4);}/* Return 1 if OP is either a register or an unaligned memory location.  */intreg_or_unaligned_mem_operand (op, mode)     rtx op;     enum machine_mode mode;{  return register_operand (op, mode) || unaligned_memory_operand (op, mode);}/* Return 1 if OP is any memory location.  During reload a pseudo matches.  */intany_memory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == MEM	  || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)	  || (reload_in_progress && GET_CODE (op) == REG	      && REGNO (op) >= FIRST_PSEUDO_REGISTER)	  || (reload_in_progress && GET_CODE (op) == SUBREG	      && GET_CODE (SUBREG_REG (op)) == REG	      && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));}/* REF is an alignable memory location.  Place an aligned SImode   reference into *PALIGNED_MEM and the number of bits to shift into   *PBITNUM.  */voidget_aligned_mem (ref, paligned_mem, pbitnum)     rtx ref;     rtx *paligned_mem, *pbitnum;{  rtx base;  HOST_WIDE_INT offset = 0;  if (GET_CODE (ref) == SUBREG)    {      offset = SUBREG_WORD (ref) * UNITS_PER_WORD;      if (BYTES_BIG_ENDIAN)	offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))		   - MIN (UNITS_PER_WORD,			  GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));      ref = SUBREG_REG (ref);    }  if (GET_CODE (ref) == REG)    ref = reg_equiv_mem[REGNO (ref)];  if (reload_in_progress)    base = find_replacement (&XEXP (ref, 0));  else    base = XEXP (ref, 0);  if (GET_CODE (base) == PLUS)    offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);  *paligned_mem = gen_rtx (MEM, SImode,			   plus_constant (base, offset & ~3));  MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref);  MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref);  RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref);  *pbitnum = GEN_INT ((offset & 3) * 8);}/* Similar, but just get the address.  Handle the two reload cases.     Add EXTRA_OFFSET to the address we return.  */rtxget_unaligned_address (ref, extra_offset)     rtx ref;     int extra_offset;{  rtx base;  HOST_WIDE_INT offset = 0;  if (GET_CODE (ref) == SUBREG)    {      offset = SUBREG_WORD (ref) * UNITS_PER_WORD;      if (BYTES_BIG_ENDIAN)	offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))		   - MIN (UNITS_PER_WORD,			  GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));      ref = SUBREG_REG (ref);    }  if (GET_CODE (ref) == REG)    ref = reg_equiv_mem[REGNO (ref)];  if (reload_in_progress)    base = find_replacement (&XEXP (ref, 0));  else    base = XEXP (ref, 0);  if (GET_CODE (base) == PLUS)    offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);  return plus_constant (base, offset + extra_offset);}/* Subfunction of the following function.  Update the flags of any MEM   found in part of X.  */static voidalpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)     rtx x;     int in_struct_p, volatile_p, unchanging_p;{  int i;  switch (GET_CODE (x))    {    case SEQUENCE:    case PARALLEL:      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)	alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,			      unchanging_p);      break;    case INSN:      alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,			    unchanging_p);      break;    case SET:      alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,			    unchanging_p);      alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,			    unchanging_p);      break;    case MEM:      MEM_IN_STRUCT_P (x) = in_struct_p;      MEM_VOLATILE_P (x) = volatile_p;      RTX_UNCHANGING_P (x) = unchanging_p;      break;    }}/* Given INSN, which is either an INSN or a SEQUENCE generated to   perform a memory operation, look for any MEMs in either a SET_DEST or   a SET_SRC and copy the in-struct, unchanging, and volatile flags from   REF into each of the MEMs found.  If REF is not a MEM, don't do   anything.  */voidalpha_set_memflags (insn, ref)     rtx insn;     rtx ref;{  /* Note that it is always safe to get these flags, though they won't     be what we think if REF is not a MEM.  */  int in_struct_p = MEM_IN_STRUCT_P (ref);  int volatile_p = MEM_VOLATILE_P (ref);  int unchanging_p = RTX_UNCHANGING_P (ref);  if (GET_CODE (ref) != MEM      || (! in_struct_p && ! volatile_p && ! unchanging_p))    return;  alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);}/* Try to output insns to set TARGET equal to the constant C if it can be   done in less than N insns.  Do all computations in MODE.  Returns the place   where the output has been placed if it can be done and the insns have been   emitted.  If it would take more than N insns, zero is returned and no   insns and emitted.  */rtxalpha_emit_set_const (target, mode, c, n)     rtx target;     enum machine_mode mode;     HOST_WIDE_INT c;     int n;{  rtx pat;  int i;  /* Try 1 insn, then 2, then up to N. */  for (i = 1; i <= n; i++)    if ((pat = alpha_emit_set_const_1 (target, mode, c, i)) != 0)      return pat;  return 0;}/* Internal routine for the above to check for N or below insns.  */static rtxalpha_emit_set_const_1 (target, mode, c, n)     rtx target;     enum machine_mode mode;     HOST_WIDE_INT c;     int n;{  HOST_WIDE_INT new = c;  int i, bits;  /* Use a pseudo if highly optimizing and still generating RTL.  */  rtx subtarget    = (flag_expensive_optimizations && rtx_equal_function_value_matters       ? 0 : target);  rtx temp;#if HOST_BITS_PER_WIDE_INT == 64  /* We are only called for SImode and DImode.  If this is SImode, ensure that     we are sign extended to a full word.  This does not make any sense when     cross-compiling on a narrow machine.  */  if (mode == SImode)    c = (c & 0xffffffff) - 2 * (c & 0x80000000);#endif  /* If this is a sign-extended 32-bit constant, we can do this in at most     three insns, so do it if we have enough insns left.  We always have     a sign-extended 32-bit constant when compiling on a narrow machine.      Note that we cannot handle the constant 0x80000000.  */  if ((HOST_BITS_PER_WIDE_INT != 64       || c >> 31 == -1 || c >> 31 == 0)      && c != 0x80000000U)    {      HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);      HOST_WIDE_INT tmp1 = c - low;      HOST_WIDE_INT high	= ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);      HOST_WIDE_INT extra = 0;      /* If HIGH will be interpreted as negative but the constant is	 positive, we must adjust it to do two ldha insns.  */      if ((high & 0x8000) != 0 && c >= 0)	{	  extra = 0x4000;	  tmp1 -= 0x40000000;	  high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);	}      if (c == low || (low == 0 && extra == 0))	return copy_to_suggested_reg (GEN_INT (c), target, mode);      else if (n >= 2 + (extra != 0))	{	  temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode);	  if (extra != 0)	    temp = expand_binop (mode, add_optab, temp, GEN_INT (extra << 16),				 subtarget, 0, OPTAB_WIDEN);	  return expand_binop (mode, add_optab, temp, GEN_INT (high << 16),			       target, 0, OPTAB_WIDEN);	}    }  /* If we couldn't do it that way, try some other methods.  But if we have     no instructions left, don't bother.  Likewise, if this is SImode and     we can't make pseudos, we can't do anything since the expand_binop

⌨️ 快捷键说明

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