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

📄 s390.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  switch (code)    {    case CONST:    case CONST_INT:    case LABEL_REF:    case SYMBOL_REF:    case CONST_DOUBLE:    case MEM:      *total = 0;      return true;    case ASHIFT:    case ASHIFTRT:    case LSHIFTRT:    case ROTATE:    case ROTATERT:    case AND:    case IOR:    case XOR:    case NEG:    case NOT:      *total = COSTS_N_INSNS (1);      return false;    case PLUS:    case MINUS:      /* Check for multiply and add.  */      if ((GET_MODE (x) == DFmode || GET_MODE (x) == SFmode)	  && GET_CODE (XEXP (x, 0)) == MULT	  && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD)	{	  /* This is the multiply and add case.  */	  if (GET_MODE (x) == DFmode)	    *total = s390_cost->madbr;	  else	    *total = s390_cost->maebr;	  *total += rtx_cost (XEXP (XEXP (x, 0), 0), MULT) 	    + rtx_cost (XEXP (XEXP (x, 0), 1), MULT) 	    + rtx_cost (XEXP (x, 1), code);	  return true;  /* Do not do an additional recursive descent.  */	}      *total = COSTS_N_INSNS (1);      return false;    case MULT:            switch (GET_MODE (x))	{	case SImode:	  {	    rtx left = XEXP (x, 0);	    rtx right = XEXP (x, 1);	    if (GET_CODE (right) == CONST_INT		&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (right), 'K', "K"))	      *total = s390_cost->mhi;	    else if (GET_CODE (left) == SIGN_EXTEND)	      *total = s390_cost->mh;	    else	      *total = s390_cost->ms;  /* msr, ms, msy */	    break;	  }	case DImode:	  {	    rtx left = XEXP (x, 0);	    rtx right = XEXP (x, 1);	    if (TARGET_64BIT)	      {		if (GET_CODE (right) == CONST_INT		    && CONST_OK_FOR_CONSTRAINT_P (INTVAL (right), 'K', "K"))		  *total = s390_cost->mghi;		else if (GET_CODE (left) == SIGN_EXTEND)		  *total = s390_cost->msgf;		else		  *total = s390_cost->msg;  /* msgr, msg */	      }	    else /* TARGET_31BIT */	      {		if (GET_CODE (left) == SIGN_EXTEND		    && GET_CODE (right) == SIGN_EXTEND)		  /* mulsidi case: mr, m */		  *total = s390_cost->m;		else if (GET_CODE (left) == ZERO_EXTEND			 && GET_CODE (right) == ZERO_EXTEND			 && TARGET_CPU_ZARCH)		  /* umulsidi case: ml, mlr */		  *total = s390_cost->ml;		else		  /* Complex calculation is required.  */		  *total = COSTS_N_INSNS (40);	      }	    break;	  }	case SFmode:	case DFmode:	  *total = s390_cost->mult_df;	  break;	default:	  return false;	}      return false;    case UDIV:    case UMOD:      if (GET_MODE (x) == TImode) 	       /* 128 bit division */	*total = s390_cost->dlgr;      else if (GET_MODE (x) == DImode)	{	  rtx right = XEXP (x, 1);	  if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */	    *total = s390_cost->dlr;	  else 	                               /* 64 by 64 bit division */	    *total = s390_cost->dlgr;	}      else if (GET_MODE (x) == SImode)         /* 32 bit division */	*total = s390_cost->dlr;      return false;    case DIV:    case MOD:      if (GET_MODE (x) == DImode)	{	  rtx right = XEXP (x, 1);	  if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */	    if (TARGET_64BIT)	      *total = s390_cost->dsgfr;	    else	      *total = s390_cost->dr;	  else 	                               /* 64 by 64 bit division */	    *total = s390_cost->dsgr;	}      else if (GET_MODE (x) == SImode)         /* 32 bit division */	*total = s390_cost->dlr;      else if (GET_MODE (x) == SFmode)	{	  if (TARGET_IEEE_FLOAT)	    *total = s390_cost->debr;	  else /* TARGET_IBM_FLOAT */	    *total = s390_cost->der;	}      else if (GET_MODE (x) == DFmode)	{	  if (TARGET_IEEE_FLOAT)	    *total = s390_cost->ddbr;	  else /* TARGET_IBM_FLOAT */	    *total = s390_cost->ddr;	}      return false;    case SQRT:      if (GET_MODE (x) == SFmode)	*total = s390_cost->sqebr;      else /* DFmode */	*total = s390_cost->sqdbr;      return false;    case SIGN_EXTEND:    case ZERO_EXTEND:      if (outer_code == MULT || outer_code == DIV || outer_code == MOD	  || outer_code == PLUS || outer_code == MINUS	  || outer_code == COMPARE)	*total = 0;      return false;    case COMPARE:      *total = COSTS_N_INSNS (1);      if (GET_CODE (XEXP (x, 0)) == AND	  && GET_CODE (XEXP (x, 1)) == CONST_INT	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)	{	  rtx op0 = XEXP (XEXP (x, 0), 0);	  rtx op1 = XEXP (XEXP (x, 0), 1);	  rtx op2 = XEXP (x, 1);	  if (memory_operand (op0, GET_MODE (op0))	      && s390_tm_ccmode (op1, op2, 0) != VOIDmode)	    return true;	  if (register_operand (op0, GET_MODE (op0))	      && s390_tm_ccmode (op1, op2, 1) != VOIDmode)	    return true;	}      return false;    default:      return false;    }}/* Return the cost of an address rtx ADDR.  */static ints390_address_cost (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 (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) == UNSPEC_PLT)    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 (register rtx op){  if (GET_CODE (op) != SYMBOL_REF)    return 0;  return SYMBOL_REF_TLS_MODEL (op);}/* 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 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  enum machine_mode elt_mode;  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);  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 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;  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)) != elt_mode	  || REGNO (SET_DEST (elt)) != dest_regno + i	  || GET_CODE (SET_SRC (elt)) != MEM	  || GET_MODE (SET_SRC (elt)) != elt_mode	  || 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 * GET_MODE_SIZE (elt_mode))	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 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  enum machine_mode elt_mode;  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);  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 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;  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)) != elt_mode	  || REGNO (SET_SRC (elt)) != src_regno + i	  || GET_CODE (SET_DEST (elt)) != MEM	  || GET_MODE (SET_DEST (elt)) != elt_mode	  || 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 * GET_MODE_SIZE (elt_mode))	return 0;    }  return 1;}/* Split DImode access register reference REG (on 64-bit) into its constituent   low and high parts, and store them into LO and HI.  Note that gen_lowpart/   gen_highpart cannot be used as they assume all registers are word-sized,   while our access registers have only half that size.  */voids390_split_access_reg (rtx reg, rtx *lo, rtx *hi){  gcc_assert (TARGET_64BIT);  gcc_assert (ACCESS_REG_P (reg));  gcc_assert (GET_MODE (reg) == DImode);  gcc_assert (!(REGNO (reg) & 1));  *lo = gen_rtx_REG (SImode, REGNO (reg) + 1);  *hi = gen_rtx_REG (SImode, REGNO (reg));}/* Return true if OP contains a symbol reference */intsymbolic_reference_mentioned_p (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 (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 (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 (register rtx op){  /* Accept all non-symbolic constants.  */  if (!SYMBOLIC_CONST (op))    return 1;  /* Accept immediate LARL operands.  */  if (TARGET_CPU_ZARCH && 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 const

⌨️ 快捷键说明

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