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

📄 s390.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	return FALSE;      if (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx))	return FALSE;    }  else    {      if (ad.base && !REG_OK_FOR_BASE_NONSTRICT_P (ad.base))	return FALSE;      if (ad.indx && !REG_OK_FOR_INDEX_NONSTRICT_P (ad.indx))	return FALSE;    }  return TRUE;}/* Return 1 if OP is a valid operand for the LA instruction.   In 31-bit, we need to prove that the result is used as an   address, as LA performs only a 31-bit addition.  */intlegitimate_la_operand_p (op)     register rtx op;{  struct s390_address addr;  if (!s390_decompose_address (op, &addr))    return FALSE;  if (TARGET_64BIT || addr.pointer)    return TRUE;  return FALSE;}/* Return 1 if OP is a valid operand for the LA instruction,   and we prefer to use LA over addition to compute it.  */   intpreferred_la_operand_p (op)     register rtx op;{  struct s390_address addr;  if (!s390_decompose_address (op, &addr))    return FALSE;  if (!TARGET_64BIT && !addr.pointer)    return FALSE;  if (addr.pointer)    return TRUE;  if ((addr.base && REG_P (addr.base) && REG_POINTER (addr.base))      || (addr.indx && REG_P (addr.indx) && REG_POINTER (addr.indx)))    return TRUE;  return FALSE;}/* Emit a forced load-address operation to load SRC into DST.   This will use the LOAD ADDRESS instruction even in situations   where legitimate_la_operand_p (SRC) returns false.  */voids390_load_address (dst, src)     rtx dst;     rtx src;{  if (TARGET_64BIT)    emit_move_insn (dst, src);  else    emit_insn (gen_force_la_31 (dst, src));}/* Return a legitimate reference for ORIG (an address) using the   register REG.  If REG is 0, a new pseudo is generated.   There are two types of references that must be handled:   1. Global data references must load the address from the GOT, via      the PIC reg.  An insn is emitted to do this load, and the reg is      returned.   2. Static data references, constant pool addresses, and code labels      compute the address as an offset from the GOT, whose base is in      the PIC reg.  Static data objects have SYMBOL_REF_FLAG set to      differentiate them from global data objects.  The returned      address is the PIC reg + an unspec constant.   GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC   reg also appears in the address.  */rtxlegitimize_pic_address (orig, reg)     rtx orig;     rtx reg;{  rtx addr = orig;  rtx new = orig;  rtx base;  if (GET_CODE (addr) == LABEL_REF      || (GET_CODE (addr) == SYMBOL_REF	  && (SYMBOL_REF_FLAG (addr)               || CONSTANT_POOL_ADDRESS_P (addr))))    {      /* This is a local symbol.  */      if (TARGET_64BIT && larl_operand (addr, VOIDmode))        {          /* Access local symbols PC-relative via LARL.               This is the same as in the non-PIC case, so it is              handled automatically ...  */        }      else        {          /* Access local symbols relative to the literal pool.  */          rtx temp = reg? reg : gen_reg_rtx (Pmode);          addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 100);          addr = gen_rtx_CONST (Pmode, addr);          addr = force_const_mem (Pmode, addr);	  emit_move_insn (temp, addr);          base = gen_rtx_REG (Pmode, BASE_REGISTER);          base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);          new = gen_rtx_PLUS (Pmode, base, temp);          if (reg != 0)            {              emit_move_insn (reg, new);              new = reg;            }        }    }  else if (GET_CODE (addr) == SYMBOL_REF)    {      if (reg == 0)        reg = gen_reg_rtx (Pmode);      if (flag_pic == 1)        {          /* Assume GOT offset < 4k.  This is handled the same way             in both 31- and 64-bit code (@GOT12).  */	  if (reload_in_progress || reload_completed)	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;          new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 110);          new = gen_rtx_CONST (Pmode, new);          new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);          new = gen_rtx_MEM (Pmode, new);          RTX_UNCHANGING_P (new) = 1;          emit_move_insn (reg, new);          new = reg;        }      else if (TARGET_64BIT)        {          /* If the GOT offset might be >= 4k, we determine the position             of the GOT entry via a PC-relative LARL (@GOTENT).  */          rtx temp = gen_reg_rtx (Pmode);          new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 111);          new = gen_rtx_CONST (Pmode, new);          emit_move_insn (temp, new);          new = gen_rtx_MEM (Pmode, temp);          RTX_UNCHANGING_P (new) = 1;          emit_move_insn (reg, new);          new = reg;        }      else        {          /* If the GOT offset might be >= 4k, we have to load it              from the literal pool (@GOT).  */          rtx temp = gen_reg_rtx (Pmode);	  if (reload_in_progress || reload_completed)	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;          addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 112);          addr = gen_rtx_CONST (Pmode, addr);          addr = force_const_mem (Pmode, addr);          emit_move_insn (temp, addr);          new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);          new = gen_rtx_MEM (Pmode, new);          RTX_UNCHANGING_P (new) = 1;          emit_move_insn (reg, new);          new = reg;        }    }        else    {      if (GET_CODE (addr) == CONST)	{	  addr = XEXP (addr, 0);	  if (GET_CODE (addr) == UNSPEC)	    {	      if (XVECLEN (addr, 0) != 1)                abort ();              switch (XINT (addr, 1))                {                  /* If someone moved an @GOT or lt-relative UNSPEC                     out of the literal pool, force them back in.  */                  case 100:                  case 112:                  case 114:                    new = force_const_mem (Pmode, orig);                    break;                  /* @GOTENT is OK as is.  */                  case 111:                    break;                  /* @PLT is OK as is on 64-bit, must be converted to                     lt-relative PLT on 31-bit.  */                  case 113:                    if (!TARGET_64BIT)                      {                        rtx temp = reg? reg : gen_reg_rtx (Pmode);                        addr = XVECEXP (addr, 0, 0);                        addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 114);                        addr = gen_rtx_CONST (Pmode, addr);                        addr = force_const_mem (Pmode, addr);	                emit_move_insn (temp, addr);                        base = gen_rtx_REG (Pmode, BASE_REGISTER);                        base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);                        new = gen_rtx_PLUS (Pmode, base, temp);                        if (reg != 0)                          {                            emit_move_insn (reg, new);                            new = reg;                          }                      }                    break;                  /* Everything else cannot happen.  */                  default:                    abort ();                }	    }	  else if (GET_CODE (addr) != PLUS)	    abort ();	}      if (GET_CODE (addr) == PLUS)	{	  rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);	  /* Check first to see if this is a constant offset              from a local symbol reference.  */	  if ((GET_CODE (op0) == LABEL_REF		|| (GET_CODE (op0) == SYMBOL_REF		    && (SYMBOL_REF_FLAG (op0)                        || CONSTANT_POOL_ADDRESS_P (op0))))	      && GET_CODE (op1) == CONST_INT)	    {              if (TARGET_64BIT && larl_operand (op0, VOIDmode))                {                  if (INTVAL (op1) & 1)                    {                      /* LARL can't handle odd offsets, so emit a                          pair of LARL and LA.  */                      rtx temp = reg? reg : gen_reg_rtx (Pmode);                      if (INTVAL (op1) < 0 || INTVAL (op1) >= 4096)                        {                          int even = INTVAL (op1) - 1;                          op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));			  op0 = gen_rtx_CONST (Pmode, op0);                          op1 = GEN_INT (1);                        }                      emit_move_insn (temp, op0);                      new = gen_rtx_PLUS (Pmode, temp, op1);                      if (reg != 0)                        {                          emit_move_insn (reg, new);                          new = reg;                        }                    }                  else                    {                      /* If the offset is even, we can just use LARL.                         This will happen automatically.  */                    }                }              else                {                  /* Access local symbols relative to the literal pool.  */                  rtx temp = reg? reg : gen_reg_rtx (Pmode);                  addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 100);                  addr = gen_rtx_PLUS (Pmode, addr, op1);                  addr = gen_rtx_CONST (Pmode, addr);                  addr = force_const_mem (Pmode, addr);        	  emit_move_insn (temp, addr);                  base = gen_rtx_REG (Pmode, BASE_REGISTER);                  base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);                  new = gen_rtx_PLUS (Pmode, base, temp);                  if (reg != 0)                    {                      emit_move_insn (reg, new);                      new = reg;                    }                }	    }          /* Now, check whether it is an LT-relative symbol plus offset             that was pulled out of the literal pool.  Force it back in.  */	  else if (GET_CODE (op0) == UNSPEC	           && GET_CODE (op1) == CONST_INT	           && XINT (op0, 1) == 100)            {	      if (XVECLEN (op0, 0) != 1)                abort ();              new = force_const_mem (Pmode, orig);            }          /* Otherwise, compute the sum.  */	  else	    {	      base = legitimize_pic_address (XEXP (addr, 0), reg);	      new  = legitimize_pic_address (XEXP (addr, 1),					     base == reg ? NULL_RTX : reg);	      if (GET_CODE (new) == CONST_INT)		new = plus_constant (base, INTVAL (new));	      else		{		  if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))		    {		      base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));		      new = XEXP (new, 1);		    }		  new = gen_rtx_PLUS (Pmode, base, new);		}	      if (GET_CODE (new) == CONST)		new = XEXP (new, 0);              new = force_operand (new, 0);	    }	}    }  return new;}/* Load the thread pointer into a register.  */static rtxget_thread_pointer (){  rtx tp;  tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);  tp = force_reg (Pmode, tp);  mark_reg_pointer (tp, BITS_PER_WORD);  return tp;}/* Construct the SYMBOL_REF for the tls_get_offset function.  */static GTY(()) rtx s390_tls_symbol;rtxs390_tls_get_offset (){  if (!s390_tls_symbol)    s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");  return s390_tls_symbol;}/* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute   this (thread-local) address.  REG may be used as temporary.  */static rtxlegitimize_tls_address (addr, reg)     rtx addr;     rtx reg;{  rtx new, tls_call, temp, base, r2, insn;  if (GET_CODE (addr) == SYMBOL_REF)    switch (tls_symbolic_operand (addr))      {      case TLS_MODEL_GLOBAL_DYNAMIC:	start_sequence ();	r2 = gen_rtx_REG (Pmode, 2);	tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLSGD);	new = gen_rtx_CONST (Pmode, tls_call);	new = force_const_mem (Pmode, new);	emit_move_insn (r2, new);	emit_call_insn (gen_call_value_tls (r2, tls_call));	insn = get_insns ();	end_sequence ();	new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);	temp = gen_reg_rtx (Pmode);	emit_libcall_block (insn, temp, r2, new);	new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);	if (reg != 0)	  {	    s390_load_address (reg, new);	    new = reg;	  }	break;      case TLS_MODEL_LOCAL_DYNAMIC:	start_sequence ();	r2 = gen_rtx_REG (Pmode, 2);	tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM);	new = gen_rtx_CONST (Pmode, tls_call);	new = force_const_mem (Pmode, new);	emit_move_insn (r2, new);	emit_call_insn (gen_call_value_tls (r2, tls_call));	insn = get_insns ();	end_sequence ();	new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM_NTPOFF);	temp = gen_reg_rtx (Pmode);	emit_libcall_block (insn, temp, r2, new);	new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);	base = gen_reg_rtx (Pmode);	s390_load_address (base, new);	new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_DTPOFF);	new = gen_rtx_CONST (Pmode, new);	new = force_const_mem (Pmode, new);	temp = gen_reg_rtx (Pmode);	emit_move_insn (temp, new);	new = gen_rtx_PLUS (Pmode, base, temp);	if (reg != 0)	  {	    s390_load_address (reg, new);	    new = reg;	  }	break;      case TLS_MODEL_INITIAL_EXEC:	if (flag_pic == 1)	  {	    /* Assume GOT offset < 4k.  This is handled the same way	       in both 31- and 64-bit code.  */	    if (reload_in_progress || reload_completed)	      regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;	    new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);	    new = gen_rtx_CONST (Pmode, new);	    new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);	    new = gen_rtx_MEM (Pmode, new);	    RTX_UNCHANGING_P (new) = 1;	    temp = gen_reg_rtx (Pmode);	    emit_move_insn (temp, new);	  }	else if (TARGET_64BIT)	  {	    /* If the GOT offset might be >= 4k, we determine the position	       of the GOT entry via a PC-relative LARL.  */	    new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);	    new = gen_rtx_CONST (Pmode, new);	    temp = gen_reg_rtx (Pmode);	    emit_move_insn (temp, new);	    new = gen_rtx_MEM (Pmode, temp);	    RTX_UNCHANGING_P (new) = 1;	    temp = gen_reg_rtx (Pmode);	    emit_move_insn (temp, new);	  }	else if (flag_pic)	  {	    /* If the GOT offset might be >= 4k, we have t

⌨️ 快捷键说明

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