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

📄 s390.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (GET_CODE (op) == SYMBOL_REF      && XSTR (op, 0)[0] != '@'      && !tls_symbolic_operand (op)      && (!flag_pic || SYMBOL_REF_FLAG (op)           || CONSTANT_POOL_ADDRESS_P (op)))    return 1;  /* Everything else must have a CONST, so strip it.  */  if (GET_CODE (op) != CONST)    return 0;  op = XEXP (op, 0);  /* Allow adding *even* constants.  */  if (GET_CODE (op) == PLUS)    {      if (GET_CODE (XEXP (op, 1)) != CONST_INT          || (INTVAL (XEXP (op, 1)) & 1) != 0)        return 0;      op = XEXP (op, 0);    }  /* Labels and local symbols allowed here as well.  */  if (GET_CODE (op) == LABEL_REF)    return 1;  if (GET_CODE (op) == SYMBOL_REF      && XSTR (op, 0)[0] != '@'      && !tls_symbolic_operand (op)      && (!flag_pic || SYMBOL_REF_FLAG (op)          || CONSTANT_POOL_ADDRESS_P (op)))    return 1;  /* Now we must have a @GOTENT offset or @PLT stub     or an @INDNTPOFF TLS offset.  */  if (GET_CODE (op) == UNSPEC      && XINT (op, 1) == 111)    return 1;  if (GET_CODE (op) == UNSPEC      && XINT (op, 1) == 113)    return 1;  if (GET_CODE (op) == UNSPEC      && XINT (op, 1) == UNSPEC_INDNTPOFF)    return 1;  return 0;}/* Helper routine to implement s_operand and s_imm_operand.   OP is the current operation.   MODE is the current operation mode.   ALLOW_IMMEDIATE specifies whether immediate operands should   be accepted or not.  */static intgeneral_s_operand (op, mode, allow_immediate)     register rtx op;     enum machine_mode mode;     int allow_immediate;{  struct s390_address addr;  /* Call general_operand first, so that we don't have to     check for many special cases.  */  if (!general_operand (op, mode))    return 0;  /* Just like memory_operand, allow (subreg (mem ...))     after reload.  */  if (reload_completed       && GET_CODE (op) == SUBREG       && GET_CODE (SUBREG_REG (op)) == MEM)    op = SUBREG_REG (op);  switch (GET_CODE (op))    {      /* Constants that we are sure will be forced to the         literal pool in reload are OK as s-operand.  Note	 that we cannot call s390_preferred_reload_class here	 because it might not be known yet at this point 	 whether the current function is a leaf or not.  */      case CONST_INT:      case CONST_DOUBLE:	if (!allow_immediate || reload_completed)	  break;	if (!legitimate_reload_constant_p (op))	  return 1;	if (!TARGET_64BIT)	  return 1;	break;      /* Memory operands are OK unless they already use an	 index register.  */      case MEM:	if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)	  return 1;	if (s390_decompose_address (XEXP (op, 0), &addr) 	    && !addr.indx)	  return 1;	break;      default:	break;    }  return 0;}/* Return true if OP is a valid S-type operand.   OP is the current operation.   MODE is the current operation mode.  */ints_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return general_s_operand (op, mode, 0);}/* Return true if OP is a valid S-type operand or an immediate    operand that can be addressed as S-type operand by forcing    it into the literal pool.   OP is the current operation.   MODE is the current operation mode.  */ints_imm_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return general_s_operand (op, mode, 1);}/* Return true if OP is a valid operand for a 'Q' constraint.   This differs from s_operand in that only memory operands   without index register are accepted, nothing else.  */intq_constraint (op)     register rtx op;{  struct s390_address addr;  if (GET_CODE (op) != MEM)    return 0;  if (!s390_decompose_address (XEXP (op, 0), &addr))    return 0;  if (addr.indx)    return 0;  return 1;}/* Return the cost of an address rtx ADDR.  */ints390_address_cost (addr)     rtx addr;{  struct s390_address ad;  if (!s390_decompose_address (addr, &ad))    return 1000;  return ad.indx? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (1);}/* Return true if OP is a valid operand for the BRAS instruction.   OP is the current operation.   MODE is the current operation mode.  */intbras_sym_operand (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  register enum rtx_code code = GET_CODE (op);  /* Allow SYMBOL_REFs.  */  if (code == SYMBOL_REF)    return 1;  /* Allow @PLT stubs.  */  if (code == CONST      && GET_CODE (XEXP (op, 0)) == UNSPEC      && XINT (XEXP (op, 0), 1) == 113)    return 1;  return 0;}/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,   otherwise return 0.  */inttls_symbolic_operand (op)     register rtx op;{  const char *symbol_str;  if (GET_CODE (op) != SYMBOL_REF)    return 0;  symbol_str = XSTR (op, 0);  if (symbol_str[0] != '%')    return 0;  return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars;}/* Return true if OP is a load multiple operation.  It is known to be a   PARALLEL and the first section will be tested.    OP is the current operation.   MODE is the current operation mode.  */intload_multiple_operation (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  int count = XVECLEN (op, 0);  unsigned int dest_regno;  rtx src_addr;  int i, off;  /* Perform a quick check so we don't blow up below.  */  if (count <= 1      || GET_CODE (XVECEXP (op, 0, 0)) != SET      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)    return 0;  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);  /* Check, is base, or base + displacement.  */  if (GET_CODE (src_addr) == REG)    off = 0;  else if (GET_CODE (src_addr) == PLUS	   && GET_CODE (XEXP (src_addr, 0)) == REG 	   && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)    {      off = INTVAL (XEXP (src_addr, 1));      src_addr = XEXP (src_addr, 0);    }  else    return 0;  if (src_addr == frame_pointer_rtx || src_addr == arg_pointer_rtx)    return 0;  for (i = 1; i < count; i++)    {      rtx elt = XVECEXP (op, 0, i);      if (GET_CODE (elt) != SET	  || GET_CODE (SET_DEST (elt)) != REG	  || GET_MODE (SET_DEST (elt)) != Pmode	  || REGNO (SET_DEST (elt)) != dest_regno + i	  || GET_CODE (SET_SRC (elt)) != MEM	  || GET_MODE (SET_SRC (elt)) != Pmode	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS	  || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)	  || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT	  || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))	     != off + i * UNITS_PER_WORD)	return 0;    }  return 1;}/* Return true if OP is a store multiple operation.  It is known to be a   PARALLEL and the first section will be tested.    OP is the current operation.   MODE is the current operation mode.  */intstore_multiple_operation (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  int count = XVECLEN (op, 0);  unsigned int src_regno;  rtx dest_addr;  int i, off;  /* Perform a quick check so we don't blow up below.  */  if (count <= 1      || GET_CODE (XVECEXP (op, 0, 0)) != SET      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)    return 0;  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);  /* Check, is base, or base + displacement.  */  if (GET_CODE (dest_addr) == REG)    off = 0;  else if (GET_CODE (dest_addr) == PLUS	   && GET_CODE (XEXP (dest_addr, 0)) == REG 	   && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)    {      off = INTVAL (XEXP (dest_addr, 1));      dest_addr = XEXP (dest_addr, 0);    }  else    return 0;  if (dest_addr == frame_pointer_rtx || dest_addr == arg_pointer_rtx)    return 0;  for (i = 1; i < count; i++)    {      rtx elt = XVECEXP (op, 0, i);      if (GET_CODE (elt) != SET	  || GET_CODE (SET_SRC (elt)) != REG	  || GET_MODE (SET_SRC (elt)) != Pmode	  || REGNO (SET_SRC (elt)) != src_regno + i	  || GET_CODE (SET_DEST (elt)) != MEM	  || GET_MODE (SET_DEST (elt)) != Pmode	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))	     != off + i * UNITS_PER_WORD)	return 0;    }  return 1;}/* Return true if OP contains a symbol reference */intsymbolic_reference_mentioned_p (op)     rtx op;{  register const char *fmt;  register int i;  if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)    return 1;  fmt = GET_RTX_FORMAT (GET_CODE (op));  for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)    {      if (fmt[i] == 'E')	{	  register int j;	  for (j = XVECLEN (op, i) - 1; j >= 0; j--)	    if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))	      return 1;	}      else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))	return 1;    }  return 0;}/* Return true if OP contains a reference to a thread-local symbol.  */inttls_symbolic_reference_mentioned_p (op)     rtx op;{  register const char *fmt;  register int i;  if (GET_CODE (op) == SYMBOL_REF)    return tls_symbolic_operand (op);  fmt = GET_RTX_FORMAT (GET_CODE (op));  for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)    {      if (fmt[i] == 'E')	{	  register int j;	  for (j = XVECLEN (op, i) - 1; j >= 0; j--)	    if (tls_symbolic_reference_mentioned_p (XVECEXP (op, i, j)))	      return 1;	}      else if (fmt[i] == 'e' && tls_symbolic_reference_mentioned_p (XEXP (op, i)))	return 1;    }  return 0;}/* Return true if OP is a legitimate general operand when    generating PIC code.  It is given that flag_pic is on    and that OP satisfies CONSTANT_P or is a CONST_DOUBLE.  */intlegitimate_pic_operand_p (op)     register rtx op;{  /* Accept all non-symbolic constants.  */  if (!SYMBOLIC_CONST (op))    return 1;  /* Reject everything else; must be handled      via emit_symbolic_move.  */  return 0;}/* Returns true if the constant value OP is a legitimate general operand.   It is given that OP satisfies CONSTANT_P or is a CONST_DOUBLE.  */intlegitimate_constant_p (op)     register rtx op;{  /* Accept all non-symbolic constants.  */  if (!SYMBOLIC_CONST (op))    return 1;  /* Accept immediate LARL operands.  */  if (TARGET_64BIT && larl_operand (op, VOIDmode))    return 1;  /* Thread-local symbols are never legal constants.  This is     so that emit_call knows that computing such addresses     might require a function call.  */  if (TLS_SYMBOLIC_CONST (op))    return 0;  /* In the PIC case, symbolic constants must *not* be     forced into the literal pool.  We accept them here,     so that they will be handled by emit_symbolic_move.  */  if (flag_pic)    return 1;  /* All remaining non-PIC symbolic constants are     forced into the literal pool.  */  return 0;}/* Determine if it's legal to put X into the constant pool.  This   is not possible if X contains the address of a symbol that is   not constant (TLS) or not known at final link time (PIC).  */static bools390_cannot_force_const_mem (x)     rtx x;{  switch (GET_CODE (x))    {    case CONST_INT:    case CONST_DOUBLE:      /* Accept all non-symbolic constants.  */      return false;    case LABEL_REF:      /* Labels are OK iff we are non-PIC.  */      return flag_pic != 0;    case SYMBOL_REF:      /* 'Naked' TLS symbol references are never OK,         non-TLS symbols are OK iff we are non-PIC.  */      if (tls_symbolic_operand (x))	return true;      else	return flag_pic != 0;    case CONST:      return s390_cannot_force_const_mem (XEXP (x, 0));    case PLUS:    case MINUS:      return s390_cannot_force_const_mem (XEXP (x, 0))	     || s390_cannot_force_const_mem (XEXP (x, 1));    case UNSPEC:      switch (XINT (x, 1))	{	/* Only lt-relative or GOT-relative UNSPECs are OK.  */	case 100:	case 104:	case 112:

⌨️ 快捷键说明

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