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

📄 s390.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* All other symbolic constants are literal pool references,     which are OK as the literal pool must be small.  */  if (GET_CODE (disp) == CONST)    return true;  return false;}/* Decompose a RTL expression ADDR for a memory address into   its components, returned in OUT.   Returns false if ADDR is not a valid memory address, true   otherwise.  If OUT is NULL, don't return the components,   but check for validity only.   Note: Only addresses in canonical form are recognized.   LEGITIMIZE_ADDRESS should convert non-canonical forms to the   canonical form so that they will be recognized.  */static ints390_decompose_address (rtx addr, struct s390_address *out){  HOST_WIDE_INT offset = 0;  rtx base = NULL_RTX;  rtx indx = NULL_RTX;  rtx disp = NULL_RTX;  rtx orig_disp;  bool pointer = false;  bool base_ptr = false;  bool indx_ptr = false;  bool literal_pool = false;  /* We may need to substitute the literal pool base register into the address     below.  However, at this point we do not know which register is going to     be used as base, so we substitute the arg pointer register.  This is going     to be treated as holding a pointer below -- it shouldn't be used for any     other purpose.  */  rtx fake_pool_base = gen_rtx_REG (Pmode, ARG_POINTER_REGNUM);  /* Decompose address into base + index + displacement.  */  if (GET_CODE (addr) == REG || GET_CODE (addr) == UNSPEC)    base = addr;  else if (GET_CODE (addr) == PLUS)    {      rtx op0 = XEXP (addr, 0);      rtx op1 = XEXP (addr, 1);      enum rtx_code code0 = GET_CODE (op0);      enum rtx_code code1 = GET_CODE (op1);      if (code0 == REG || code0 == UNSPEC)	{	  if (code1 == REG || code1 == UNSPEC)	    {	      indx = op0;	/* index + base */	      base = op1;	    }	  else	    {	      base = op0;	/* base + displacement */	      disp = op1;	    }	}      else if (code0 == PLUS)	{	  indx = XEXP (op0, 0);	/* index + base + disp */	  base = XEXP (op0, 1);	  disp = op1;	}      else	{	  return false;	}    }  else    disp = addr;		/* displacement */  /* Extract integer part of displacement.  */  orig_disp = disp;  if (disp)    {      if (GET_CODE (disp) == CONST_INT)	{	  offset = INTVAL (disp);	  disp = NULL_RTX;	}      else if (GET_CODE (disp) == CONST	       && GET_CODE (XEXP (disp, 0)) == PLUS	       && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)	{	  offset = INTVAL (XEXP (XEXP (disp, 0), 1));	  disp = XEXP (XEXP (disp, 0), 0);	}    }  /* Strip off CONST here to avoid special case tests later.  */  if (disp && GET_CODE (disp) == CONST)    disp = XEXP (disp, 0);  /* We can convert literal pool addresses to     displacements by basing them off the base register.  */  if (disp && GET_CODE (disp) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (disp))    {      /* Either base or index must be free to hold the base register.  */      if (!base)        base = fake_pool_base, literal_pool = true;      else if (!indx)        indx = fake_pool_base, literal_pool = true;      else        return false;      /* Mark up the displacement.  */      disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),			     UNSPEC_LTREL_OFFSET);    }  /* Validate base register.  */  if (base)    {      if (GET_CODE (base) == UNSPEC)	switch (XINT (base, 1))	  {	  case UNSPEC_LTREF:	    if (!disp)	      disp = gen_rtx_UNSPEC (Pmode, 				     gen_rtvec (1, XVECEXP (base, 0, 0)),				     UNSPEC_LTREL_OFFSET);	    else	      return false;	    base = XVECEXP (base, 0, 1);	    break;	  case UNSPEC_LTREL_BASE:	    if (XVECLEN (base, 0) == 1)	      base = fake_pool_base, literal_pool = true;	    else	      base = XVECEXP (base, 0, 1);	    break;	  default:	    return false;	  }      if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)	return false;      if (REGNO (base) == STACK_POINTER_REGNUM	  || REGNO (base) == FRAME_POINTER_REGNUM	  || ((reload_completed || reload_in_progress)	      && frame_pointer_needed	      && REGNO (base) == HARD_FRAME_POINTER_REGNUM)	  || REGNO (base) == ARG_POINTER_REGNUM          || (flag_pic              && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))        pointer = base_ptr = true;      if ((reload_completed || reload_in_progress)	  && base == cfun->machine->base_reg)        pointer = base_ptr = literal_pool = true;    }  /* Validate index register.  */  if (indx)    {      if (GET_CODE (indx) == UNSPEC)	switch (XINT (indx, 1))	  {	  case UNSPEC_LTREF:	    if (!disp)	      disp = gen_rtx_UNSPEC (Pmode, 				     gen_rtvec (1, XVECEXP (indx, 0, 0)),				     UNSPEC_LTREL_OFFSET);	    else	      return false;	    indx = XVECEXP (indx, 0, 1);	    break;	  case UNSPEC_LTREL_BASE:	    if (XVECLEN (indx, 0) == 1)	      indx = fake_pool_base, literal_pool = true;	    else	      indx = XVECEXP (indx, 0, 1);	    break;	  default:	    return false;	  }      if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)	return false;      if (REGNO (indx) == STACK_POINTER_REGNUM	  || REGNO (indx) == FRAME_POINTER_REGNUM	  || ((reload_completed || reload_in_progress)	      && frame_pointer_needed	      && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)	  || REGNO (indx) == ARG_POINTER_REGNUM          || (flag_pic              && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))        pointer = indx_ptr = true;      if ((reload_completed || reload_in_progress)	  && indx == cfun->machine->base_reg)        pointer = indx_ptr = literal_pool = true;    }  /* Prefer to use pointer as base, not index.  */  if (base && indx && !base_ptr      && (indx_ptr || (!REG_POINTER (base) && REG_POINTER (indx))))    {      rtx tmp = base;      base = indx;      indx = tmp;    }  /* Validate displacement.  */  if (!disp)    {      /* If virtual registers are involved, the displacement will change later 	 anyway as the virtual registers get eliminated.  This could make a 	 valid displacement invalid, but it is more likely to make an invalid 	 displacement valid, because we sometimes access the register save area 	 via negative offsets to one of those registers.	 Thus we don't check the displacement for validity here.  If after	 elimination the displacement turns out to be invalid after all,	 this is fixed up by reload in any case.  */      if (base != arg_pointer_rtx 	  && indx != arg_pointer_rtx 	  && base != return_address_pointer_rtx 	  && indx != return_address_pointer_rtx	  && base != frame_pointer_rtx 	  && indx != frame_pointer_rtx	  && base != virtual_stack_vars_rtx 	  && indx != virtual_stack_vars_rtx)	if (!DISP_IN_RANGE (offset))	  return false;    }  else    {      /* All the special cases are pointers.  */      pointer = true;      /* In the small-PIC case, the linker converts @GOT         and @GOTNTPOFF offsets to possible displacements.  */      if (GET_CODE (disp) == UNSPEC          && (XINT (disp, 1) == UNSPEC_GOT	      || XINT (disp, 1) == UNSPEC_GOTNTPOFF)	  && offset == 0	  && flag_pic == 1)        {	  ;        }      /* Accept chunkified literal pool symbol references.  */      else if (cfun && cfun->machine	       && cfun->machine->decomposed_literal_pool_addresses_ok_p	       && GET_CODE (disp) == MINUS               && GET_CODE (XEXP (disp, 0)) == LABEL_REF               && GET_CODE (XEXP (disp, 1)) == LABEL_REF)        {	  ;        }      /* Accept literal pool references.  */      else if (GET_CODE (disp) == UNSPEC	       && XINT (disp, 1) == UNSPEC_LTREL_OFFSET)        {	  orig_disp = gen_rtx_CONST (Pmode, disp);	  if (offset)	    {	      /* If we have an offset, make sure it does not		 exceed the size of the constant pool entry.  */	      rtx sym = XVECEXP (disp, 0, 0);	      if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))		return false;              orig_disp = plus_constant (orig_disp, offset);	    }        }      else	return false;    }  if (!base && !indx)    pointer = true;  if (out)    {      out->base = base;      out->indx = indx;      out->disp = orig_disp;      out->pointer = pointer;      out->literal_pool = literal_pool;    }  return true;}/* Decompose a RTL expression OP for a shift count into its components,   and return the base register in BASE and the offset in OFFSET.   Return true if OP is a valid shift count, false if not.  */bools390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset){  HOST_WIDE_INT off = 0;  /* We can have an integer constant, an address register,     or a sum of the two.  */  if (GET_CODE (op) == CONST_INT)    {      off = INTVAL (op);      op = NULL_RTX;    }  if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)    {      off = INTVAL (XEXP (op, 1));      op = XEXP (op, 0);    }  while (op && GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  if (op && GET_CODE (op) != REG)    return false;  if (offset)    *offset = off;  if (base)    *base = op;   return true;}/* Return true if CODE is a valid address without index.  */bools390_legitimate_address_without_index_p (rtx op){  struct s390_address addr;  if (!s390_decompose_address (XEXP (op, 0), &addr))    return false;  if (addr.indx)    return false;  return true;}/* Return 1 if OP is a valid operand for a C constraint, 0 else.  */ints390_extra_constraint_str (rtx op, int c, const char * str){  struct s390_address addr;  gcc_assert (c == str[0]);  /* Check for offsettable variants of memory constraints.  */  if (c == 'A')    {      /* Only accept non-volatile MEMs.  */      if (!MEM_P (op) || MEM_VOLATILE_P (op))	return 0;      if ((reload_completed || reload_in_progress)	  ? !offsettable_memref_p (op)	  : !offsettable_nonstrict_memref_p (op))	return 0;      c = str[1];    }  /* Check for non-literal-pool variants of memory constraints.  */  else if (c == 'B')    {      if (GET_CODE (op) != MEM)	return 0;      if (!s390_decompose_address (XEXP (op, 0), &addr))	return 0;      if (addr.literal_pool)	return 0;      c = str[1];    }  switch (c)    {    case 'Q':      if (GET_CODE (op) != MEM)	return 0;      if (!s390_decompose_address (XEXP (op, 0), &addr))	return 0;      if (addr.indx)	return 0;      if (TARGET_LONG_DISPLACEMENT)	{	  if (!s390_short_displacement (addr.disp))	    return 0;	}      break;    case 'R':      if (GET_CODE (op) != MEM)	return 0;      if (TARGET_LONG_DISPLACEMENT)	{	  if (!s390_decompose_address (XEXP (op, 0), &addr))	    return 0;	  if (!s390_short_displacement (addr.disp))	    return 0;	}      break;    case 'S':      if (!TARGET_LONG_DISPLACEMENT)	return 0;      if (GET_CODE (op) != MEM)	return 0;      if (!s390_decompose_address (XEXP (op, 0), &addr))	return 0;      if (addr.indx)	return 0;      if (s390_short_displacement (addr.disp))	return 0;      break;    case 'T':      if (!TARGET_LONG_DISPLACEMENT)	return 0;      if (GET_CODE (op) != MEM)	return 0;      /* Any invalid address here will be fixed up by reload,	 so accept it for the most generic constraint.  */      if (s390_decompose_address (XEXP (op, 0), &addr)	  && s390_short_displacement (addr.disp))	return 0;      break;    case 'U':      if (TARGET_LONG_DISPLACEMENT)	{	  if (!s390_decompose_address (op, &addr))	    return 0;	  if (!s390_short_displacement (addr.disp))	    return 0;	}      break;    case 'W':      if (!TARGET_LONG_DISPLACEMENT)	return 0;      /* Any invalid address here will be fixed up by reload,	 so accept it for the most generic constraint.  */      if (s390_decompose_address (op, &addr)	  && s390_short_displacement (addr.disp))	return 0;      break;    case 'Y':      /* Simply check for the basic form of a shift count.  Reload will	 take care of making sure we have a proper base register.  */      if (!s390_decompose_shift_count (op, NULL, NULL))	return 0;      break;    default:      return 0;    }  return 1;}/* Return true if VALUE matches the constraint STR.  */int

⌨️ 快捷键说明

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