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

📄 ia64.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define TARGET_CANNOT_FORCE_CONST_MEM ia64_cannot_force_const_memstruct gcc_target targetm = TARGET_INITIALIZER;typedef enum  {    ADDR_AREA_NORMAL,	/* normal address area */    ADDR_AREA_SMALL	/* addressable by "addl" (-2MB < addr < 2MB) */  }ia64_addr_area;static GTY(()) tree small_ident1;static GTY(()) tree small_ident2;static voidinit_idents (void){  if (small_ident1 == 0)    {      small_ident1 = get_identifier ("small");      small_ident2 = get_identifier ("__small__");    }}/* Retrieve the address area that has been chosen for the given decl.  */static ia64_addr_areaia64_get_addr_area (tree decl){  tree model_attr;  model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));  if (model_attr)    {      tree id;      init_idents ();      id = TREE_VALUE (TREE_VALUE (model_attr));      if (id == small_ident1 || id == small_ident2)	return ADDR_AREA_SMALL;    }  return ADDR_AREA_NORMAL;}static treeia64_handle_model_attribute (tree *node, tree name, tree args,			     int flags ATTRIBUTE_UNUSED, bool *no_add_attrs){  ia64_addr_area addr_area = ADDR_AREA_NORMAL;  ia64_addr_area area;  tree arg, decl = *node;  init_idents ();  arg = TREE_VALUE (args);  if (arg == small_ident1 || arg == small_ident2)    {      addr_area = ADDR_AREA_SMALL;    }  else    {      warning ("invalid argument of %qs attribute",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  switch (TREE_CODE (decl))    {    case VAR_DECL:      if ((DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl))	   == FUNCTION_DECL)	  && !TREE_STATIC (decl))	{	  error ("%Jan address area attribute cannot be specified for "		 "local variables", decl, decl);	  *no_add_attrs = true;	}      area = ia64_get_addr_area (decl);      if (area != ADDR_AREA_NORMAL && addr_area != area)	{	  error ("%Jaddress area of '%s' conflicts with previous "		 "declaration", decl, decl);	  *no_add_attrs = true;	}      break;    case FUNCTION_DECL:      error ("%Jaddress area attribute cannot be specified for functions",	     decl, decl);      *no_add_attrs = true;      break;    default:      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));      *no_add_attrs = true;      break;    }  return NULL_TREE;}static voidia64_encode_addr_area (tree decl, rtx symbol){  int flags;  flags = SYMBOL_REF_FLAGS (symbol);  switch (ia64_get_addr_area (decl))    {    case ADDR_AREA_NORMAL: break;    case ADDR_AREA_SMALL: flags |= SYMBOL_FLAG_SMALL_ADDR; break;    default: abort ();    }  SYMBOL_REF_FLAGS (symbol) = flags;}static voidia64_encode_section_info (tree decl, rtx rtl, int first){  default_encode_section_info (decl, rtl, first);  /* 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      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))    ia64_encode_addr_area (decl, XEXP (rtl, 0));}/* Implement CONST_OK_FOR_LETTER_P.  */boolia64_const_ok_for_letter_p (HOST_WIDE_INT value, char c){  switch (c)    {    case 'I':      return CONST_OK_FOR_I (value);    case 'J':      return CONST_OK_FOR_J (value);    case 'K':      return CONST_OK_FOR_K (value);    case 'L':      return CONST_OK_FOR_L (value);    case 'M':      return CONST_OK_FOR_M (value);    case 'N':      return CONST_OK_FOR_N (value);    case 'O':      return CONST_OK_FOR_O (value);    case 'P':      return CONST_OK_FOR_P (value);    default:      return false;    }}/* Implement CONST_DOUBLE_OK_FOR_LETTER_P.  */boolia64_const_double_ok_for_letter_p (rtx value, char c){  switch (c)    {    case 'G':      return CONST_DOUBLE_OK_FOR_G (value);    default:      return false;    }}/* Implement EXTRA_CONSTRAINT.  */boolia64_extra_constraint (rtx value, char c){  switch (c)    {    case 'Q':      /* Non-volatile memory for FP_REG loads/stores.  */      return memory_operand(value, VOIDmode) && !MEM_VOLATILE_P (value);    case 'R':      /* 1..4 for shladd arguments.  */      return (GET_CODE (value) == CONST_INT	      && INTVAL (value) >= 1 && INTVAL (value) <= 4);    case 'S':      /* Non-post-inc memory for asms and other unsavory creatures.  */      return (GET_CODE (value) == MEM	      && GET_RTX_CLASS (GET_CODE (XEXP (value, 0))) != RTX_AUTOINC	      && (reload_in_progress || memory_operand (value, VOIDmode)));    case 'T':      /* Symbol ref to small-address-area.  */      return small_addr_symbolic_operand (value, VOIDmode);    case 'U':      /* Vector zero.  */      return value == CONST0_RTX (GET_MODE (value));    case 'W':      /* An integer vector, such that conversion to an integer yields a	 value appropriate for an integer 'J' constraint.  */      if (GET_CODE (value) == CONST_VECTOR	  && GET_MODE_CLASS (GET_MODE (value)) == MODE_VECTOR_INT)	{	  value = simplify_subreg (DImode, value, GET_MODE (value), 0);	  return ia64_const_ok_for_letter_p (INTVAL (value), 'J');	}      return false;    case 'Y':      /* A V2SF vector containing elements that satisfy 'G'.  */      return	(GET_CODE (value) == CONST_VECTOR	 && GET_MODE (value) == V2SFmode	 && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 0), 'G')	 && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 1), 'G'));    default:      return false;    }}/* Return 1 if the operands of a move are ok.  */intia64_move_ok (rtx dst, rtx src){  /* If we're under init_recog_no_volatile, we'll not be able to use     memory_operand.  So check the code directly and don't worry about     the validity of the underlying address, which should have been     checked elsewhere anyway.  */  if (GET_CODE (dst) != MEM)    return 1;  if (GET_CODE (src) == MEM)    return 0;  if (register_operand (src, VOIDmode))    return 1;  /* Otherwise, this must be a constant, and that either 0 or 0.0 or 1.0.  */  if (INTEGRAL_MODE_P (GET_MODE (dst)))    return src == const0_rtx;  else    return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);}intaddp4_optimize_ok (rtx op1, rtx op2){  return (basereg_operand (op1, GET_MODE(op1)) !=	  basereg_operand (op2, GET_MODE(op2)));}/* Check if OP is a mask suitable for use with SHIFT in a dep.z instruction.   Return the length of the field, or <= 0 on failure.  */intia64_depz_field_mask (rtx rop, rtx rshift){  unsigned HOST_WIDE_INT op = INTVAL (rop);  unsigned HOST_WIDE_INT shift = INTVAL (rshift);  /* Get rid of the zero bits we're shifting in.  */  op >>= shift;  /* We must now have a solid block of 1's at bit 0.  */  return exact_log2 (op + 1);}/* Return the TLS model to use for ADDR.  */static enum tls_modeltls_symbolic_operand_type (rtx addr){  enum tls_model tls_kind = 0;  if (GET_CODE (addr) == CONST)    {      if (GET_CODE (XEXP (addr, 0)) == PLUS	  && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)        tls_kind = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (addr, 0), 0));    }  else if (GET_CODE (addr) == SYMBOL_REF)    tls_kind = SYMBOL_REF_TLS_MODEL (addr);  return tls_kind;}/* Return true if X is a constant that is valid for some immediate   field in an instruction.  */boolia64_legitimate_constant_p (rtx x){  switch (GET_CODE (x))    {    case CONST_INT:    case LABEL_REF:      return true;    case CONST_DOUBLE:      if (GET_MODE (x) == VOIDmode)	return true;      return CONST_DOUBLE_OK_FOR_G (x);    case CONST:    case SYMBOL_REF:      return tls_symbolic_operand_type (x) == 0;    default:      return false;    }}/* Don't allow TLS addresses to get spilled to memory.  */static boolia64_cannot_force_const_mem (rtx x){  return tls_symbolic_operand_type (x) != 0;}/* Expand a symbolic constant load.  */boolia64_expand_load_address (rtx dest, rtx src){  gcc_assert (GET_CODE (dest) == REG);  /* ILP32 mode still loads 64-bits of data from the GOT.  This avoids     having to pointer-extend the value afterward.  Other forms of address     computation below are also more natural to compute as 64-bit quantities.     If we've been given an SImode destination register, change it.  */  if (GET_MODE (dest) != Pmode)    dest = gen_rtx_REG_offset (dest, Pmode, REGNO (dest), 0);  if (TARGET_NO_PIC)    return false;  if (small_addr_symbolic_operand (src, VOIDmode))    return false;  if (TARGET_AUTO_PIC)    emit_insn (gen_load_gprel64 (dest, src));  else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (src))    emit_insn (gen_load_fptr (dest, src));  else if (sdata_symbolic_operand (src, VOIDmode))    emit_insn (gen_load_gprel (dest, src));  else    {      HOST_WIDE_INT addend = 0;      rtx tmp;      /* We did split constant offsets in ia64_expand_move, and we did try	 to keep them split in move_operand, but we also allowed reload to	 rematerialize arbitrary constants rather than spill the value to	 the stack and reload it.  So we have to be prepared here to split	 them apart again.  */      if (GET_CODE (src) == CONST)	{	  HOST_WIDE_INT hi, lo;	  hi = INTVAL (XEXP (XEXP (src, 0), 1));	  lo = ((hi & 0x3fff) ^ 0x2000) - 0x2000;	  hi = hi - lo;	  if (lo != 0)	    {	      addend = lo;	      src = plus_constant (XEXP (XEXP (src, 0), 0), hi);	    }	}      tmp = gen_rtx_HIGH (Pmode, src);      tmp = gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);      emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));      tmp = gen_rtx_LO_SUM (Pmode, dest, src);      emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));      if (addend)	{	  tmp = gen_rtx_PLUS (Pmode, dest, GEN_INT (addend));	  emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));	}    }  return true;}static GTY(()) rtx gen_tls_tga;static rtxgen_tls_get_addr (void){  if (!gen_tls_tga)    gen_tls_tga = init_one_libfunc ("__tls_get_addr");  return gen_tls_tga;}static GTY(()) rtx thread_pointer_rtx;static rtxgen_thread_pointer (void){  if (!thread_pointer_rtx)    thread_pointer_rtx = gen_rtx_REG (Pmode, 13);  return thread_pointer_rtx;}static rtxia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1,			 HOST_WIDE_INT addend){  rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;  rtx orig_op0 = op0, orig_op1 = op1;  HOST_WIDE_INT addend_lo, addend_hi;  addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;  addend_hi = addend - addend_lo;  switch (tls_kind)    {    case TLS_MODEL_GLOBAL_DYNAMIC:      start_sequence ();      tga_op1 = gen_reg_rtx (Pmode);      emit_insn (gen_load_dtpmod (tga_op1, op1));      tga_op2 = gen_reg_rtx (Pmode);      emit_insn (gen_load_dtprel (tga_op2, op1));      tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,					 LCT_CONST, Pmode, 2, tga_op1,					 Pmode, tga_op2, Pmode);      insns = get_insns ();

⌨️ 快捷键说明

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