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

📄 alpha.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	      && zap_mask (CONST_DOUBLE_LOW (value))	      && zap_mask (CONST_DOUBLE_HIGH (value)));    default:      return false;    }}/* Implements CONST_DOUBLE_OK_FOR_LETTER_P.  Return true if VALUE   matches for C.  */boolalpha_extra_constraint (value, c)     rtx value;     int c;{  switch (c)    {    case 'Q':      return normal_memory_operand (value, VOIDmode);    case 'R':      return direct_call_operand (value, Pmode);    case 'S':      return (GET_CODE (value) == CONST_INT	      && (unsigned HOST_WIDE_INT) INTVAL (value) < 64);    case 'T':      return GET_CODE (value) == HIGH;    case 'U':      return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);    default:      return false;    }}/* Return 1 if this function can directly return via $26.  */intdirect_return (){  return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK	  && reload_completed	  && alpha_sa_size () == 0	  && get_frame_size () == 0	  && current_function_outgoing_args_size == 0	  && current_function_pretend_args_size == 0);}/* Return the ADDR_VEC associated with a tablejump insn.  */rtxalpha_tablejump_addr_vec (insn)     rtx insn;{  rtx tmp;  tmp = JUMP_LABEL (insn);  if (!tmp)    return NULL_RTX;  tmp = NEXT_INSN (tmp);  if (!tmp)    return NULL_RTX;  if (GET_CODE (tmp) == JUMP_INSN      && GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)    return PATTERN (tmp);  return NULL_RTX;}/* Return the label of the predicted edge, or CONST0_RTX if we don't know.  */rtxalpha_tablejump_best_label (insn)     rtx insn;{  rtx jump_table = alpha_tablejump_addr_vec (insn);  rtx best_label = NULL_RTX;  /* ??? Once the CFG doesn't keep getting completely rebuilt, look     there for edge frequency counts from profile data.  */  if (jump_table)    {      int n_labels = XVECLEN (jump_table, 1);      int best_count = -1;      int i, j;      for (i = 0; i < n_labels; i++)	{	  int count = 1;	  for (j = i + 1; j < n_labels; j++)	    if (XEXP (XVECEXP (jump_table, 1, i), 0)		== XEXP (XVECEXP (jump_table, 1, j), 0))	      count++;	  if (count > best_count)	    best_count = count, best_label = XVECEXP (jump_table, 1, i);	}    }  return best_label ? best_label : const0_rtx;}/* Return true if the function DECL will be placed in the default text   section.  *//* ??? Ideally we'd be able to always move from a SYMBOL_REF back to the   decl, as that would allow us to determine if two functions are in the   same section, which is what we really want to know.  */static booldecl_in_text_section (decl)     tree decl;{  return (DECL_SECTION_NAME (decl) == NULL_TREE	  && ! (flag_function_sections	        || (targetm.have_named_sections		    && DECL_ONE_ONLY (decl))));}/* If we are referencing a function that is static, make the SYMBOL_REF   special.  We use this to see indicate we can branch to this function   without setting PV or restoring GP.    If this is a variable that is known to be defined locally, add "@v"   to the name.  If in addition the variable is to go in .sdata/.sbss,   then add "@s" instead.  */voidalpha_encode_section_info (decl)     tree decl;{  const char *symbol_str;  bool is_local, is_small;  if (TREE_CODE (decl) == FUNCTION_DECL)    {      /* We mark public functions once they are emitted; otherwise we	 don't know that they exist in this unit of translation.  */      if (TREE_PUBLIC (decl))	return;      /* Do not mark functions that are not in .text; otherwise we	 don't know that they are near enough for a direct branch.  */      if (! decl_in_text_section (decl))	return;      SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;      return;    }  /* Early out if we're not going to do anything with this data.  */  if (! TARGET_EXPLICIT_RELOCS)    return;  /* Careful not to prod global register variables.  */  if (TREE_CODE (decl) != VAR_DECL      || GET_CODE (DECL_RTL (decl)) != MEM      || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)    return;      symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);  /* A variable is considered "local" if it is defined in this module.  */  if (DECL_EXTERNAL (decl))    is_local = false;  /* Linkonce and weak data is never local.  */  else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))    is_local = false;  else if (! TREE_PUBLIC (decl))    is_local = true;  /* If PIC, then assume that any global name can be overridden by     symbols resolved from other modules.  */  else if (flag_pic)    is_local = false;  /* Uninitialized COMMON variable may be unified with symbols     resolved from other modules.  */  else if (DECL_COMMON (decl)	   && (DECL_INITIAL (decl) == NULL	       || DECL_INITIAL (decl) == error_mark_node))    is_local = false;  /* Otherwise we're left with initialized (or non-common) global data     which is of necessity defined locally.  */  else    is_local = true;  /* Determine if DECL will wind up in .sdata/.sbss.  */  is_small = false;  if (DECL_SECTION_NAME (decl))    {      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));      if (strcmp (section, ".sdata") == 0	  || strcmp (section, ".sbss") == 0)	is_small = true;    }  else    {      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));      /* If the variable has already been defined in the output file, then it	 is too late to put it in sdata if it wasn't put there in the first	 place.  The test is here rather than above, because if it is already	 in sdata, then it can stay there.  */      if (TREE_ASM_WRITTEN (decl))	;      /* If this is an incomplete type with size 0, then we can't put it in	 sdata because it might be too big when completed.  */      else if (size > 0 && size <= g_switch_value)	is_small = true;    }  /* Finally, encode this into the symbol string.  */  if (is_local)    {      const char *string;      char *newstr;      size_t len;      if (symbol_str[0] == '@')	{	  if (symbol_str[1] == (is_small ? 's' : 'v'))	    return;	  symbol_str += 2;	}      len = strlen (symbol_str) + 1;      newstr = alloca (len + 2);      newstr[0] = '@';      newstr[1] = (is_small ? 's' : 'v');      memcpy (newstr + 2, symbol_str, len);	        string = ggc_alloc_string (newstr, len + 2 - 1);      XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;    }  else if (symbol_str[0] == '@')    {      /* We're hosed.  This can happen when the user adds a weak	 attribute after rtl generation.  They should have gotten	 a warning about unspecified behaviour from varasm.c.  */    }}/* legitimate_address_p recognizes an RTL expression that is a valid   memory address for an instruction.  The MODE argument is the   machine mode for the MEM expression that wants to use this address.   For Alpha, we have either a constant address or the sum of a   register and a constant address, or just a register.  For DImode,   any of those forms can be surrounded with an AND that clear the   low-order three bits; this is an "unaligned" access.  */boolalpha_legitimate_address_p (mode, x, strict)     enum machine_mode mode;     rtx x;     int strict;{  /* If this is an ldq_u type address, discard the outer AND.  */  if (mode == DImode      && GET_CODE (x) == AND      && GET_CODE (XEXP (x, 1)) == CONST_INT      && INTVAL (XEXP (x, 1)) == -8)    x = XEXP (x, 0);  /* Discard non-paradoxical subregs.  */  if (GET_CODE (x) == SUBREG      && (GET_MODE_SIZE (GET_MODE (x))	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))    x = SUBREG_REG (x);  /* Unadorned general registers are valid.  */  if (REG_P (x)      && (strict	  ? STRICT_REG_OK_FOR_BASE_P (x)	  : NONSTRICT_REG_OK_FOR_BASE_P (x)))    return true;  /* Constant addresses (i.e. +/- 32k) are valid.  */  if (CONSTANT_ADDRESS_P (x))    return true;  /* Register plus a small constant offset is valid.  */  if (GET_CODE (x) == PLUS)    {      rtx ofs = XEXP (x, 1);      x = XEXP (x, 0);      /* Discard non-paradoxical subregs.  */      if (GET_CODE (x) == SUBREG          && (GET_MODE_SIZE (GET_MODE (x))	      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))	x = SUBREG_REG (x);      if (REG_P (x))	{	  if (! strict	      && NONSTRICT_REG_OK_FP_BASE_P (x)	      && GET_CODE (ofs) == CONST_INT)	    return true;	  if ((strict	       ? STRICT_REG_OK_FOR_BASE_P (x)	       : NONSTRICT_REG_OK_FOR_BASE_P (x))	      && CONSTANT_ADDRESS_P (ofs))	    return true;	}      else if (GET_CODE (x) == ADDRESSOF	       && GET_CODE (ofs) == CONST_INT)	return true;    }  /* If we're managing explicit relocations, LO_SUM is valid, as     are small data symbols.  */  else if (TARGET_EXPLICIT_RELOCS)    {      if (small_symbolic_operand (x, Pmode))	return true;      if (GET_CODE (x) == LO_SUM)	{	  rtx ofs = XEXP (x, 1);	  x = XEXP (x, 0);	  /* Discard non-paradoxical subregs.  */	  if (GET_CODE (x) == SUBREG	      && (GET_MODE_SIZE (GET_MODE (x))		  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))	    x = SUBREG_REG (x);	  /* Must have a valid base register.  */	  if (! (REG_P (x)		 && (strict		     ? STRICT_REG_OK_FOR_BASE_P (x)		     : NONSTRICT_REG_OK_FOR_BASE_P (x))))	    return false;	  /* The symbol must be local.  */	  if (local_symbolic_operand (ofs, Pmode))	    return true;	}    }  return false;}/* Try machine-dependent ways of modifying an illegitimate address   to be legitimate.  If we find one, return the new, valid address.  */rtxalpha_legitimize_address (x, scratch, mode)     rtx x;     rtx scratch;     enum machine_mode mode ATTRIBUTE_UNUSED;{  HOST_WIDE_INT addend;  /* If the address is (plus reg const_int) and the CONST_INT is not a     valid offset, compute the high part of the constant and add it to     the register.  Then our address is (plus temp low-part-const).  */  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == REG      && GET_CODE (XEXP (x, 1)) == CONST_INT      && ! CONSTANT_ADDRESS_P (XEXP (x, 1)))    {      addend = INTVAL (XEXP (x, 1));      x = XEXP (x, 0);      goto split_addend;    }  /* If the address is (const (plus FOO const_int)), find the low-order     part of the CONST_INT.  Then load FOO plus any high-order part of the     CONST_INT into a register.  Our address is (plus reg low-part-const).     This is done to reduce the number of GOT entries.  */  if (!no_new_pseudos      && GET_CODE (x) == CONST      && GET_CODE (XEXP (x, 0)) == PLUS      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)    {      addend = INTVAL (XEXP (XEXP (x, 0), 1));      x = force_reg (Pmode, XEXP (XEXP (x, 0), 0));      goto split_addend;    }  /* If we have a (plus reg const), emit the load as in (2), then add     the two registers, and finally generate (plus reg low-part-const) as     our address.  */  if (!no_new_pseudos      && GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == REG      && GET_CODE (XEXP (x, 1)) == CONST      && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS      && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)    {      addend = INTVAL (XEXP (XEXP (XEXP (x, 1), 0), 1));      x = expand_simple_binop (Pmode, PLUS, XEXP (x, 0),			       XEXP (XEXP (XEXP (x, 1), 0), 0),			       NULL_RTX, 1, OPTAB_LIB_WIDEN);      goto split_addend;    }  /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */  if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))    {      if (local_symbolic_operand (x, Pmode))	{	  if (small_symbolic_operand (x, Pmode))	    return x;	  else	    {	      if (!no_new_pseudos)	        scratch = gen_reg_rtx (Pmode);	      emit_insn (gen_rtx_SET (VOIDmode, scratch,				      gen_rtx_HIGH (Pmode, x)));	      return gen_rtx_LO_SUM (Pmode, scratch, x);	    }	}    }  return NULL; split_addend:  {    HOST_WIDE_INT low, high;    low = ((addend & 0xffff) ^ 0x8000) - 0x8000;    addend -= low;    high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;    addend -= high;    if (addend)      x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),			       (no_new_pseudos ? scratch : NULL_RTX),			       1, OPTAB_LIB_WIDEN);    if (high)      x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),			       (no_new_pseudos ? scratch : NULL_RTX),			       1, OPTAB_LIB_WIDEN);    return plus_constant (x, low);  }}/* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a   small symbolic operand until after reload.  At which point we need   to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))   so that sched2 has the proper dependency information.  */intsome_small_symbolic_operand (x, mode)     rtx x;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return for_each_rtx (&x, some_small_symbolic_operand_1, NULL);}static intsome_small_symbolic_operand_1 (px, data)     rtx *px;     void *data ATTRIBUTE_UNUSED;{  rtx x = *px;  /* Don't re-split.  */  if (GET_CODE (x) == LO_SUM)    return -1;  return small_symbolic_operand (x, Pmode) != 0;}rtxsplit_small_symbolic_operand (x)     rtx x;{  x = copy_insn (x);

⌨️ 快捷键说明

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