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

📄 s390.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
      bit1 = exact_log2 (INTVAL (op2));      bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));      if (bit0 != -1 && bit1 != -1)        return bit0 > bit1 ? CCT1mode : CCT2mode;    }  return VOIDmode;}/* Given a comparison code OP (EQ, NE, etc.) and the operands   OP0 and OP1 of a COMPARE, return the mode to be used for the   comparison.  */enum machine_modes390_select_ccmode (enum rtx_code code, rtx op0, rtx op1){  switch (code)    {      case EQ:      case NE:	if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)	    && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)	  return CCAPmode;	if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT	    && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))	  return CCAPmode;	if ((GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS	     || GET_CODE (op1) == NEG)	    && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)	  return CCLmode;	if (GET_CODE (op0) == AND)	  {	    /* Check whether we can potentially do it via TM.  */	    enum machine_mode ccmode;	    ccmode = s390_tm_ccmode (XEXP (op0, 1), op1, 1);	    if (ccmode != VOIDmode)	      {		/* Relax CCTmode to CCZmode to allow fall-back to AND		   if that turns out to be beneficial.  */	        return ccmode == CCTmode ? CCZmode : ccmode;	      }	  }	if (register_operand (op0, HImode)	    && GET_CODE (op1) == CONST_INT	    && (INTVAL (op1) == -1 || INTVAL (op1) == 65535))	  return CCT3mode;	if (register_operand (op0, QImode)	    && GET_CODE (op1) == CONST_INT	    && (INTVAL (op1) == -1 || INTVAL (op1) == 255))	  return CCT3mode;	return CCZmode;      case LE:      case LT:      case GE:      case GT:	/* The only overflow condition of NEG and ABS happens when	   -INT_MAX is used as parameter, which stays negative. So	   we have an overflow from a positive value to a negative. 	   Using CCAP mode the resulting cc can be used for comparisons.  */	if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)	    && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)	  return CCAPmode; 	/* If constants are involved in an add instruction it is possible to use 	   the resulting cc for comparisons with zero. Knowing the sign of the	   constant the overflow behavior gets predictable. e.g.: 	     int a, b; if ((b = a + c) > 0)   	   with c as a constant value: c < 0 -> CCAN and c >= 0 -> CCAP  */	if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT	    && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))	  {	    if (INTVAL (XEXP((op0), 1)) < 0)	      return CCANmode;	    else	      return CCAPmode;	  }	/* Fall through.  */      case UNORDERED:      case ORDERED:      case UNEQ:      case UNLE:      case UNLT:      case UNGE:      case UNGT:      case LTGT:	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)	    && GET_CODE (op1) != CONST_INT)	  return CCSRmode;	return CCSmode;      case LTU:      case GEU:	if (GET_CODE (op0) == PLUS	    && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)	  return CCL1mode;	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)	    && GET_CODE (op1) != CONST_INT)	  return CCURmode;	return CCUmode;      case LEU:      case GTU:	if (GET_CODE (op0) == MINUS	    && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)	  return CCL2mode;	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)	    && GET_CODE (op1) != CONST_INT)	  return CCURmode;	return CCUmode;      default:	gcc_unreachable ();    }}/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one   that we can implement more efficiently.  */voids390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1){  /* Convert ZERO_EXTRACT back to AND to enable TM patterns.  */  if ((*code == EQ || *code == NE)      && *op1 == const0_rtx      && GET_CODE (*op0) == ZERO_EXTRACT      && GET_CODE (XEXP (*op0, 1)) == CONST_INT      && GET_CODE (XEXP (*op0, 2)) == CONST_INT      && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))    {      rtx inner = XEXP (*op0, 0);      HOST_WIDE_INT modesize = GET_MODE_BITSIZE (GET_MODE (inner));      HOST_WIDE_INT len = INTVAL (XEXP (*op0, 1));      HOST_WIDE_INT pos = INTVAL (XEXP (*op0, 2));      if (len > 0 && len < modesize	  && pos >= 0 && pos + len <= modesize	  && modesize <= HOST_BITS_PER_WIDE_INT)	{	  unsigned HOST_WIDE_INT block;	  block = ((unsigned HOST_WIDE_INT) 1 << len) - 1;	  block <<= modesize - pos - len;	  *op0 = gen_rtx_AND (GET_MODE (inner), inner,			      gen_int_mode (block, GET_MODE (inner)));	}    }  /* Narrow AND of memory against immediate to enable TM.  */  if ((*code == EQ || *code == NE)      && *op1 == const0_rtx      && GET_CODE (*op0) == AND      && GET_CODE (XEXP (*op0, 1)) == CONST_INT      && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))    {      rtx inner = XEXP (*op0, 0);      rtx mask = XEXP (*op0, 1);      /* Ignore paradoxical SUBREGs if all extra bits are masked out.  */      if (GET_CODE (inner) == SUBREG	  && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (inner)))	  && (GET_MODE_SIZE (GET_MODE (inner))	      >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner))))	  && ((INTVAL (mask)               & GET_MODE_MASK (GET_MODE (inner))               & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))	      == 0))	inner = SUBREG_REG (inner);      /* Do not change volatile MEMs.  */      if (MEM_P (inner) && !MEM_VOLATILE_P (inner))	{	  int part = s390_single_part (XEXP (*op0, 1),				       GET_MODE (inner), QImode, 0);	  if (part >= 0)	    {	      mask = gen_int_mode (s390_extract_part (mask, QImode, 0), QImode);	      inner = adjust_address_nv (inner, QImode, part);	      *op0 = gen_rtx_AND (QImode, inner, mask);	    }	}    }  /* Narrow comparisons against 0xffff to HImode if possible.  */  if ((*code == EQ || *code == NE)      && GET_CODE (*op1) == CONST_INT      && INTVAL (*op1) == 0xffff      && SCALAR_INT_MODE_P (GET_MODE (*op0))      && (nonzero_bits (*op0, GET_MODE (*op0)) 	  & ~(unsigned HOST_WIDE_INT) 0xffff) == 0)    {      *op0 = gen_lowpart (HImode, *op0);      *op1 = constm1_rtx;    }  /* Remove redundant UNSPEC_CMPINT conversions if possible.  */  if (GET_CODE (*op0) == UNSPEC      && XINT (*op0, 1) == UNSPEC_CMPINT      && XVECLEN (*op0, 0) == 1      && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode      && GET_CODE (XVECEXP (*op0, 0, 0)) == REG      && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM      && *op1 == const0_rtx)    {      enum rtx_code new_code = UNKNOWN;      switch (*code)	{	  case EQ: new_code = EQ;  break;	  case NE: new_code = NE;  break;	  case LT: new_code = GTU; break;	  case GT: new_code = LTU; break;	  case LE: new_code = GEU; break;	  case GE: new_code = LEU; break;	  default: break;	}      if (new_code != UNKNOWN)	{	  *op0 = XVECEXP (*op0, 0, 0);	  *code = new_code;	}    }  /* Simplify cascaded EQ, NE with const0_rtx.  */  if ((*code == NE || *code == EQ)      && (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)      && GET_MODE (*op0) == SImode      && GET_MODE (XEXP (*op0, 0)) == CCZ1mode      && REG_P (XEXP (*op0, 0))      && XEXP (*op0, 1) == const0_rtx      && *op1 == const0_rtx)    {      if ((*code == EQ && GET_CODE (*op0) == NE)          || (*code == NE && GET_CODE (*op0) == EQ))	*code = EQ;      else	*code = NE;      *op0 = XEXP (*op0, 0);    }  /* Prefer register over memory as first operand.  */  if (MEM_P (*op0) && REG_P (*op1))    {      rtx tem = *op0; *op0 = *op1; *op1 = tem;      *code = swap_condition (*code);    }}/* Emit a compare instruction suitable to implement the comparison   OP0 CODE OP1.  Return the correct condition RTL to be placed in   the IF_THEN_ELSE of the conditional branch testing the result.  */rtxs390_emit_compare (enum rtx_code code, rtx op0, rtx op1){  enum machine_mode mode = s390_select_ccmode (code, op0, op1);  rtx ret = NULL_RTX;  /* Do not output a redundant compare instruction if a compare_and_swap     pattern already computed the result and the machine modes are compatible.  */  if (s390_compare_emitted       && (s390_cc_modes_compatible (GET_MODE (s390_compare_emitted), mode)	  == GET_MODE (s390_compare_emitted)))    ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);   else    {      rtx cc = gen_rtx_REG (mode, CC_REGNUM);            emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));      ret = gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);     }  s390_compare_emitted = NULL_RTX;  return ret;}/* Emit a jump instruction to TARGET.  If COND is NULL_RTX, emit an   unconditional jump, else a conditional jump under condition COND.  */voids390_emit_jump (rtx target, rtx cond){  rtx insn;  target = gen_rtx_LABEL_REF (VOIDmode, target);  if (cond)    target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, target, pc_rtx);  insn = gen_rtx_SET (VOIDmode, pc_rtx, target);  emit_jump_insn (insn);}/* Return branch condition mask to implement a branch   specified by CODE.  Return -1 for invalid comparisons.  */ints390_branch_condition_mask (rtx code){  const int CC0 = 1 << 3;  const int CC1 = 1 << 2;  const int CC2 = 1 << 1;  const int CC3 = 1 << 0;  gcc_assert (GET_CODE (XEXP (code, 0)) == REG);  gcc_assert (REGNO (XEXP (code, 0)) == CC_REGNUM);  gcc_assert (XEXP (code, 1) == const0_rtx);  switch (GET_MODE (XEXP (code, 0)))    {    case CCZmode:    case CCZ1mode:      switch (GET_CODE (code))        {        case EQ:	return CC0;	case NE:	return CC1 | CC2 | CC3;	default:	return -1;        }      break;    case CCT1mode:      switch (GET_CODE (code))        {        case EQ:	return CC1;	case NE:	return CC0 | CC2 | CC3;	default:	return -1;        }      break;    case CCT2mode:      switch (GET_CODE (code))        {        case EQ:	return CC2;	case NE:	return CC0 | CC1 | CC3;	default:	return -1;        }      break;    case CCT3mode:      switch (GET_CODE (code))        {        case EQ:	return CC3;	case NE:	return CC0 | CC1 | CC2;	default:	return -1;        }      break;    case CCLmode:      switch (GET_CODE (code))        {        case EQ:	return CC0 | CC2;	case NE:	return CC1 | CC3;	default:	return -1;        }      break;    case CCL1mode:      switch (GET_CODE (code))        {	case LTU:	return CC2 | CC3;  /* carry */	case GEU:	return CC0 | CC1;  /* no carry */	default:	return -1;        }      break;    case CCL2mode:      switch (GET_CODE (code))        {	case GTU:	return CC0 | CC1;  /* borrow */	case LEU:	return CC2 | CC3;  /* no borrow */	default:	return -1;        }      break;    case CCL3mode:      switch (GET_CODE (code))	{	case EQ:	return CC0 | CC2;	case NE:	return CC1 | CC3;	case LTU:	return CC1;	case GTU:	return CC3;	case LEU:	return CC1 | CC2;	case GEU:	return CC2 | CC3;	default:	return -1;	}    case CCUmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;        case NE:	return CC1 | CC2 | CC3;        case LTU:	return CC1;        case GTU:	return CC2;        case LEU:	return CC0 | CC1;        case GEU:	return CC0 | CC2;	default:	return -1;        }      break;    case CCURmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;        case NE:	return CC2 | CC1 | CC3;        case LTU:	return CC2;        case GTU:	return CC1;        case LEU:	return CC0 | CC2;        case GEU:	return CC0 | CC1;	default:	return -1;        }      break;    case CCAPmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;        case NE:	return CC1 | CC2 | CC3;        case LT:	return CC1 | CC3;        case GT:	return CC2;        case LE:	return CC0 | CC1 | CC3;        case GE:	return CC0 | CC2;	default:	return -1;        }      break;    case CCANmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;        case NE:	return CC1 | CC2 | CC3;        case LT:	return CC1;        case GT:	return CC2 | CC3;        case LE:	return CC0 | CC1;        case GE:	return CC0 | CC2 | CC3;	default:	return -1;        }      break;    case CCSmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;        case NE:	return CC1 | CC2 | CC3;        case LT:	return CC1;        case GT:	return CC2;        case LE:	return CC0 | CC1;        case GE:	return CC0 | CC2;	case UNORDERED:	return CC3;	case ORDERED:	return CC0 | CC1 | CC2;	case UNEQ:	return CC0 | CC3;        case UNLT:	return CC1 | CC3;        case UNGT:	return CC2 | CC3;        case UNLE:	return CC0 | CC1 | CC3;        case UNGE:	return CC0 | CC2 | CC3;	case LTGT:	return CC1 | CC2;	default:	return -1;        }      break;    case CCSRmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;        case NE:	return CC2 | CC1 | CC3;        case LT:	return CC2;        case GT:	return CC1;        case LE:	return CC0 | CC2;        case GE:	return CC0 | CC1;	case UNORDERED:	return CC3;	case ORDERED:	return CC0 | CC2 | CC1;	case UNEQ:	return CC0 | CC3;        case UNLT:	return CC2 | CC3;        case UNGT:	return CC1 | CC3;        case UNLE:	return CC0 | CC2 | CC3;        case UNGE:	return CC0 | CC1 | CC3;	case LTGT:	return CC2 | CC1;	default:	return -1;        }      break;    default:      return -1;    }}

⌨️ 快捷键说明

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