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

📄 ia64.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      end_sequence ();      if (GET_MODE (op0) != Pmode)	op0 = tga_ret;      emit_libcall_block (insns, op0, tga_ret, op1);      break;    case TLS_MODEL_LOCAL_DYNAMIC:      /* ??? This isn't the completely proper way to do local-dynamic	 If the call to __tls_get_addr is used only by a single symbol,	 then we should (somehow) move the dtprel to the second arg	 to avoid the extra add.  */      start_sequence ();      tga_op1 = gen_reg_rtx (Pmode);      emit_insn (gen_load_dtpmod (tga_op1, op1));      tga_op2 = const0_rtx;      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 ();      end_sequence ();      tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),				UNSPEC_LD_BASE);      tmp = gen_reg_rtx (Pmode);      emit_libcall_block (insns, tmp, tga_ret, tga_eqv);      if (!register_operand (op0, Pmode))	op0 = gen_reg_rtx (Pmode);      if (TARGET_TLS64)	{	  emit_insn (gen_load_dtprel (op0, op1));	  emit_insn (gen_adddi3 (op0, tmp, op0));	}      else	emit_insn (gen_add_dtprel (op0, op1, tmp));      break;    case TLS_MODEL_INITIAL_EXEC:      op1 = plus_constant (op1, addend_hi);      addend = addend_lo;      tmp = gen_reg_rtx (Pmode);      emit_insn (gen_load_tprel (tmp, op1));      if (!register_operand (op0, Pmode))	op0 = gen_reg_rtx (Pmode);      emit_insn (gen_adddi3 (op0, tmp, gen_thread_pointer ()));      break;    case TLS_MODEL_LOCAL_EXEC:      if (!register_operand (op0, Pmode))	op0 = gen_reg_rtx (Pmode);      op1 = orig_op1;      addend = 0;      if (TARGET_TLS64)	{	  emit_insn (gen_load_tprel (op0, op1));	  emit_insn (gen_adddi3 (op0, op0, gen_thread_pointer ()));	}      else	emit_insn (gen_add_tprel (op0, op1, gen_thread_pointer ()));      break;    default:      abort ();    }  if (addend)    op0 = expand_simple_binop (Pmode, PLUS, op0, GEN_INT (addend),			       orig_op0, 1, OPTAB_DIRECT);  if (orig_op0 == op0)    return NULL_RTX;  if (GET_MODE (orig_op0) == Pmode)    return op0;  return gen_lowpart (GET_MODE (orig_op0), op0);}rtxia64_expand_move (rtx op0, rtx op1){  enum machine_mode mode = GET_MODE (op0);  if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))    op1 = force_reg (mode, op1);  if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))    {      HOST_WIDE_INT addend = 0;      enum tls_model tls_kind;      rtx sym = op1;      if (GET_CODE (op1) == CONST	  && GET_CODE (XEXP (op1, 0)) == PLUS	  && GET_CODE (XEXP (XEXP (op1, 0), 1)) == CONST_INT)	{	  addend = INTVAL (XEXP (XEXP (op1, 0), 1));	  sym = XEXP (XEXP (op1, 0), 0);	}      tls_kind = tls_symbolic_operand_type (sym);      if (tls_kind)	return ia64_expand_tls_address (tls_kind, op0, sym, addend);      if (any_offset_symbol_operand (sym, mode))	addend = 0;      else if (aligned_offset_symbol_operand (sym, mode))	{	  HOST_WIDE_INT addend_lo, addend_hi;	      	  addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;	  addend_hi = addend - addend_lo;	  if (addend_lo != 0)	    {	      op1 = plus_constant (sym, addend_hi);	      addend = addend_lo;	    }	  else	    addend = 0;	}      else	op1 = sym;      if (reload_completed)	{	  /* We really should have taken care of this offset earlier.  */	  gcc_assert (addend == 0);	  if (ia64_expand_load_address (op0, op1))	    return NULL_RTX;	}      if (addend)	{	  rtx subtarget = no_new_pseudos ? op0 : gen_reg_rtx (mode);	  emit_insn (gen_rtx_SET (VOIDmode, subtarget, op1));	  op1 = expand_simple_binop (mode, PLUS, subtarget,				     GEN_INT (addend), op0, 1, OPTAB_DIRECT);	  if (op0 == op1)	    return NULL_RTX;	}    }  return op1;}/* Split a move from OP1 to OP0 conditional on COND.  */voidia64_emit_cond_move (rtx op0, rtx op1, rtx cond){  rtx insn, first = get_last_insn ();  emit_move_insn (op0, op1);  for (insn = get_last_insn (); insn != first; insn = PREV_INSN (insn))    if (INSN_P (insn))      PATTERN (insn) = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond),					  PATTERN (insn));}/* Split a post-reload TImode or TFmode reference into two DImode   components.  This is made extra difficult by the fact that we do   not get any scratch registers to work with, because reload cannot   be prevented from giving us a scratch that overlaps the register   pair involved.  So instead, when addressing memory, we tweak the   pointer register up and back down with POST_INCs.  Or up and not   back down when we can get away with it.   REVERSED is true when the loads must be done in reversed order   (high word first) for correctness.  DEAD is true when the pointer   dies with the second insn we generate and therefore the second   address must not carry a postmodify.   May return an insn which is to be emitted after the moves.  */static rtxia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead){  rtx fixup = 0;  switch (GET_CODE (in))    {    case REG:      out[reversed] = gen_rtx_REG (DImode, REGNO (in));      out[!reversed] = gen_rtx_REG (DImode, REGNO (in) + 1);      break;    case CONST_INT:    case CONST_DOUBLE:      /* Cannot occur reversed.  */      if (reversed) abort ();            if (GET_MODE (in) != TFmode)	split_double (in, &out[0], &out[1]);      else	/* split_double does not understand how to split a TFmode	   quantity into a pair of DImode constants.  */	{	  REAL_VALUE_TYPE r;	  unsigned HOST_WIDE_INT p[2];	  long l[4];  /* TFmode is 128 bits */	  REAL_VALUE_FROM_CONST_DOUBLE (r, in);	  real_to_target (l, &r, TFmode);	  if (FLOAT_WORDS_BIG_ENDIAN)	    {	      p[0] = (((unsigned HOST_WIDE_INT) l[0]) << 32) + l[1];	      p[1] = (((unsigned HOST_WIDE_INT) l[2]) << 32) + l[3];	    }	  else	    {	      p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2];	      p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0];	    }	  out[0] = GEN_INT (p[0]);	  out[1] = GEN_INT (p[1]);	}      break;    case MEM:      {	rtx base = XEXP (in, 0);	rtx offset;	switch (GET_CODE (base))	  {	  case REG:	    if (!reversed)	      {		out[0] = adjust_automodify_address		  (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);		out[1] = adjust_automodify_address		  (in, DImode, dead ? 0 : gen_rtx_POST_DEC (Pmode, base), 8);	      }	    else	      {		/* Reversal requires a pre-increment, which can only		   be done as a separate insn.  */		emit_insn (gen_adddi3 (base, base, GEN_INT (8)));		out[0] = adjust_automodify_address		  (in, DImode, gen_rtx_POST_DEC (Pmode, base), 8);		out[1] = adjust_address (in, DImode, 0);	      }	    break;	  case POST_INC:	    if (reversed || dead) abort ();	    /* Just do the increment in two steps.  */	    out[0] = adjust_automodify_address (in, DImode, 0, 0);	    out[1] = adjust_automodify_address (in, DImode, 0, 8);	    break;	  case POST_DEC:	    if (reversed || dead) abort ();	    /* Add 8, subtract 24.  */	    base = XEXP (base, 0);	    out[0] = adjust_automodify_address	      (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);	    out[1] = adjust_automodify_address	      (in, DImode,	       gen_rtx_POST_MODIFY (Pmode, base, plus_constant (base, -24)),	       8);	    break;	  case POST_MODIFY:	    if (reversed || dead) abort ();	    /* Extract and adjust the modification.  This case is	       trickier than the others, because we might have an	       index register, or we might have a combined offset that	       doesn't fit a signed 9-bit displacement field.  We can	       assume the incoming expression is already legitimate.  */	    offset = XEXP (base, 1);	    base = XEXP (base, 0);	    out[0] = adjust_automodify_address	      (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);	    if (GET_CODE (XEXP (offset, 1)) == REG)	      {		/* Can't adjust the postmodify to match.  Emit the		   original, then a separate addition insn.  */		out[1] = adjust_automodify_address (in, DImode, 0, 8);		fixup = gen_adddi3 (base, base, GEN_INT (-8));	      }	    else if (GET_CODE (XEXP (offset, 1)) != CONST_INT)	      abort ();	    else if (INTVAL (XEXP (offset, 1)) < -256 + 8)	      {		/* Again the postmodify cannot be made to match, but		   in this case it's more efficient to get rid of the		   postmodify entirely and fix up with an add insn.  */		out[1] = adjust_automodify_address (in, DImode, base, 8);		fixup = gen_adddi3 (base, base,				    GEN_INT (INTVAL (XEXP (offset, 1)) - 8));	      }	    else	      {		/* Combined offset still fits in the displacement field.		   (We cannot overflow it at the high end.)  */		out[1] = adjust_automodify_address		  (in, DImode,		   gen_rtx_POST_MODIFY (Pmode, base,		     gen_rtx_PLUS (Pmode, base,				   GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),		   8);	      }	    break;	  default:	    abort ();	  }	break;      }    default:      abort ();    }  return fixup;}/* Split a TImode or TFmode move instruction after reload.   This is used by *movtf_internal and *movti_internal.  */voidia64_split_tmode_move (rtx operands[]){  rtx in[2], out[2], insn;  rtx fixup[2];  bool dead = false;  bool reversed = false;  /* It is possible for reload to decide to overwrite a pointer with     the value it points to.  In that case we have to do the loads in     the appropriate order so that the pointer is not destroyed too     early.  Also we must not generate a postmodify for that second     load, or rws_access_regno will abort.  */  if (GET_CODE (operands[1]) == MEM      && reg_overlap_mentioned_p (operands[0], operands[1]))    {      rtx base = XEXP (operands[1], 0);      while (GET_CODE (base) != REG)	base = XEXP (base, 0);      if (REGNO (base) == REGNO (operands[0]))	reversed = true;      dead = true;    }  /* Another reason to do the moves in reversed order is if the first     element of the target register pair is also the second element of     the source register pair.  */  if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG      && REGNO (operands[0]) == REGNO (operands[1]) + 1)    reversed = true;  fixup[0] = ia64_split_tmode (in, operands[1], reversed, dead);  fixup[1] = ia64_split_tmode (out, operands[0], reversed, dead);#define MAYBE_ADD_REG_INC_NOTE(INSN, EXP)				\  if (GET_CODE (EXP) == MEM						\      && (GET_CODE (XEXP (EXP, 0)) == POST_MODIFY			\	  || GET_CODE (XEXP (EXP, 0)) == POST_INC			\	  || GET_CODE (XEXP (EXP, 0)) == POST_DEC))			\    REG_NOTES (INSN) = gen_rtx_EXPR_LIST (REG_INC,			\					  XEXP (XEXP (EXP, 0), 0),	\					  REG_NOTES (INSN))  insn = emit_insn (gen_rtx_SET (VOIDmode, out[0], in[0]));  MAYBE_ADD_REG_INC_NOTE (insn, in[0]);  MAYBE_ADD_REG_INC_NOTE (insn, out[0]);  insn = emit_insn (gen_rtx_SET (VOIDmode, out[1], in[1]));  MAYBE_ADD_REG_INC_NOTE (insn, in[1]);  MAYBE_ADD_REG_INC_NOTE (insn, out[1]);  if (fixup[0])    emit_insn (fixup[0]);  if (fixup[1])    emit_insn (fixup[1]);#undef MAYBE_ADD_REG_INC_NOTE}/* ??? Fixing GR->FR XFmode moves during reload is hard.  You need to go   through memory plus an extra GR scratch register.  Except that you can   either get the first from SECONDARY_MEMORY_NEEDED or the second from   SECONDARY_RELOAD_CLASS, but not both.   We got into problems in the first place by allowing a construct like   (subreg:XF (reg:TI)), which we got from a union containing a long double.   This solution attempts to prevent this situation from occurring.  When   we see something like the above, we spill the inner register to memory.  */rtxspill_xfmode_operand (rtx in, int force){  if (GET_CODE (in) == SUBREG      && GET_MODE (SUBREG_REG (in)) == TImode      && GET_CODE (SUBREG_REG (in)) == REG)    {      rtx memt = assign_stack_temp (TImode, 16, 0);      emit_move_insn (memt, SUBREG_REG (in));      return adjust_address (memt, XFmode, 0);    }  else if (force && GET_CODE (in) == REG)    {      rtx memx = assign_stack_temp (XFmode, 16, 0);      emit_move_insn (memx, in);      return memx;    }  else    return in;}/* Emit comparison instruction if necessary, returning the expression   that holds the compare result in the proper mode.  */static GTY(()) rtx cmptf_libfunc;rtxia64_expand_compare (enum rtx_code code, enum machine_mode mode){  rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1;  rtx cmp;  /* If we have a BImode input, then we already have a compare result, and

⌨️ 快捷键说明

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