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

📄 recog.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Return 1 if ADDR is an address-expression whose effect depends   on the mode of the memory reference it is used in.   Autoincrement addressing is a typical example of mode-dependence   because the amount of the increment depends on the mode.  */intmode_dependent_address_p (addr)     rtx addr;{  GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);  return 0; win:  return 1;}/* Return 1 if OP is a general operand   other than a memory ref with a mode dependent address.  */intmode_independent_operand (op, mode)     enum machine_mode mode;     rtx op;{  rtx addr;  if (! general_operand (op, mode))    return 0;  if (GET_CODE (op) != MEM)    return 1;  addr = XEXP (op, 0);  GO_IF_MODE_DEPENDENT_ADDRESS (addr, lose);  return 1; lose:  return 0;}/* Given an operand OP that is a valid memory reference   which satisfies offsettable_memref_p,   return a new memory reference whose address has been adjusted by OFFSET.   OFFSET should be positive and less than the size of the object referenced.*/rtxadj_offsettable_operand (op, offset)     rtx op;     int offset;{  register enum rtx_code code = GET_CODE (op);  if (code == MEM)     {      register rtx y = XEXP (op, 0);      register rtx new;      if (CONSTANT_ADDRESS_P (y))	{	  new = gen_rtx (MEM, GET_MODE (op), plus_constant_for_output (y, offset));	  RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);	  return new;	}      if (GET_CODE (y) == PLUS)	{	  rtx z = y;	  register rtx *const_loc;	  op = copy_rtx (op);	  z = XEXP (op, 0);	  const_loc = find_constant_term_loc (&z);	  if (const_loc)	    {	      *const_loc = plus_constant_for_output (*const_loc, offset);	      return op;	    }	}      new = gen_rtx (MEM, GET_MODE (op), plus_constant_for_output (y, offset));      RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);      return new;    }  abort ();}#ifdef REGISTER_CONSTRAINTS/* Check the operands of an insn (found in recog_operands)   against the insn's operand constraints (found via INSN_CODE_NUM)   and return 1 if they are valid.   WHICH_ALTERNATIVE is set to a number which indicates which   alternative of constraints was matched: 0 for the first alternative,   1 for the next, etc.   In addition, when two operands are match   and it happens that the output operand is (reg) while the   input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),   make the output operand look like the input.   This is because the output operand is the one the template will print.   This is used in final, just before printing the assembler code and by   the routines that determine an insn's attribute.   If STRICT is a positive non-zero value, it means that we have been   called after reload has been completed.  In that case, we must   do all checks strictly.  If it is zero, it means that we have been called   before reload has completed.  In that case, we first try to see if we can   find an alternative that matches strictly.  If not, we try again, this   time assuming that reload will fix up the insn.  This provides a "best   guess" for the alternative and is used to compute attributes of insns prior   to reload.  A negative value of STRICT is used for this internal call.  */struct funny_match{  int this, other;};intconstrain_operands (insn_code_num, strict)     int insn_code_num;     int strict;{  char *constraints[MAX_RECOG_OPERANDS];  int matching_operands[MAX_RECOG_OPERANDS];  enum op_type {OP_IN, OP_OUT, OP_INOUT} op_types[MAX_RECOG_OPERANDS];  int earlyclobber[MAX_RECOG_OPERANDS];  register int c;  int noperands = insn_n_operands[insn_code_num];  struct funny_match funny_match[MAX_RECOG_OPERANDS];  int funny_match_index;  int nalternatives = insn_n_alternatives[insn_code_num];  if (noperands == 0 || nalternatives == 0)    return 1;  for (c = 0; c < noperands; c++)    {      constraints[c] = insn_operand_constraint[insn_code_num][c];      matching_operands[c] = -1;      op_types[c] = OP_IN;    }  which_alternative = 0;  while (which_alternative < nalternatives)    {      register int opno;      int lose = 0;      funny_match_index = 0;      for (opno = 0; opno < noperands; opno++)	{	  register rtx op = recog_operand[opno];	  enum machine_mode mode = GET_MODE (op);	  register char *p = constraints[opno];	  int offset = 0;	  int win = 0;	  int val;	  earlyclobber[opno] = 0;	  if (GET_CODE (op) == SUBREG)	    {	      if (GET_CODE (SUBREG_REG (op)) == REG		  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)		offset = SUBREG_WORD (op);	      op = SUBREG_REG (op);	    }	  /* An empty constraint or empty alternative	     allows anything which matched the pattern.  */	  if (*p == 0 || *p == ',')	    win = 1;	  while (*p && (c = *p++) != ',')	    switch (c)	      {	      case '?':	      case '!':	      case '*':	      case '%':		break;	      case '#':		/* Ignore rest of this alternative as far as		   constraint checking is concerned.  */		while (*p && *p != ',')		  p++;		break;	      case '=':		op_types[opno] = OP_OUT;		break;	      case '+':		op_types[opno] = OP_INOUT;		break;	      case '&':		earlyclobber[opno] = 1;		break;	      case '0':	      case '1':	      case '2':	      case '3':	      case '4':		/* This operand must be the same as a previous one.		   This kind of constraint is used for instructions such		   as add when they take only two operands.		   Note that the lower-numbered operand is passed first.		   If we are not testing strictly, assume that this constraint		   will be satisfied.  */		if (strict < 0)		  val = 1;		else		  val = operands_match_p (recog_operand[c - '0'],					  recog_operand[opno]);		matching_operands[opno] = c - '0';		matching_operands[c - '0'] = opno;		if (val != 0)		  win = 1;		/* If output is *x and input is *--x,		   arrange later to change the output to *--x as well,		   since the output op is the one that will be printed.  */		if (val == 2 && strict > 0)		  {		    funny_match[funny_match_index].this = opno;		    funny_match[funny_match_index++].other = c - '0';		  }		break;	      case 'p':		/* p is used for address_operands.  When we are called by		   gen_reload, no one will have checked that the address is		   strictly valid, i.e., that all pseudos requiring hard regs		   have gotten them.  */		if (strict <= 0		    || (strict_memory_address_p			(insn_operand_mode[insn_code_num][opno], op)))		  win = 1;		break;		/* No need to check general_operand again;		   it was done in insn-recog.c.  */	      case 'g':		/* Anything goes unless it is a REG and really has a hard reg		   but the hard reg is not in the class GENERAL_REGS.  */		if (strict < 0		    || GENERAL_REGS == ALL_REGS		    || GET_CODE (op) != REG		    || (reload_in_progress			&& REGNO (op) >= FIRST_PSEUDO_REGISTER)		    || reg_fits_class_p (op, GENERAL_REGS, offset, mode))		  win = 1;		break;	      case 'r':		if (strict < 0		    || (strict == 0			&& GET_CODE (op) == REG			&& REGNO (op) >= FIRST_PSEUDO_REGISTER)		    || (strict == 0 && GET_CODE (op) == SCRATCH)		    || (GET_CODE (op) == REG			&& ((GENERAL_REGS == ALL_REGS			     && REGNO (op) < FIRST_PSEUDO_REGISTER)			    || reg_fits_class_p (op, GENERAL_REGS,						 offset, mode))))		  win = 1;		break;	      case 'X':		/* This is used for a MATCH_SCRATCH in the cases when we		   don't actually need anything.  So anything goes any time. */		win = 1;		break;	      case 'm':		if (GET_CODE (op) == MEM		    /* Before reload, accept what reload can turn into mem.  */		    || (strict < 0 && CONSTANT_P (op))		    /* During reload, accept a pseudo  */		    || (reload_in_progress && GET_CODE (op) == REG			&& REGNO (op) >= FIRST_PSEUDO_REGISTER))		  win = 1;		break;	      case '<':		if (GET_CODE (op) == MEM		    && (GET_CODE (XEXP (op, 0)) == PRE_DEC			|| GET_CODE (XEXP (op, 0)) == POST_DEC))		  win = 1;		break;	      case '>':		if (GET_CODE (op) == MEM		    && (GET_CODE (XEXP (op, 0)) == PRE_INC			|| GET_CODE (XEXP (op, 0)) == POST_INC))		  win = 1;		break;	      case 'E':#ifndef REAL_ARITHMETIC		/* Match any CONST_DOUBLE, but only if		   we can examine the bits of it reliably.  */		if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT		     || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)		    && GET_MODE (op) != VOIDmode && ! flag_pretend_float)		  break;#endif		if (GET_CODE (op) == CONST_DOUBLE)		  win = 1;		break;	      case 'F':		if (GET_CODE (op) == CONST_DOUBLE)		  win = 1;		break;	      case 'G':	      case 'H':		if (GET_CODE (op) == CONST_DOUBLE		    && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))		  win = 1;		break;	      case 's':		if (GET_CODE (op) == CONST_INT		    || (GET_CODE (op) == CONST_DOUBLE			&& GET_MODE (op) == VOIDmode))		  break;	      case 'i':		if (CONSTANT_P (op))		  win = 1;		break;	      case 'n':		if (GET_CODE (op) == CONST_INT		    || (GET_CODE (op) == CONST_DOUBLE			&& GET_MODE (op) == VOIDmode))		  win = 1;		break;	      case 'I':	      case 'J':	      case 'K':	      case 'L':	      case 'M':	      case 'N':	      case 'O':	      case 'P':		if (GET_CODE (op) == CONST_INT		    && CONST_OK_FOR_LETTER_P (INTVAL (op), c))		  win = 1;		break;#ifdef EXTRA_CONSTRAINT              case 'Q':              case 'R':              case 'S':              case 'T':              case 'U':		if (EXTRA_CONSTRAINT (op, c))		  win = 1;		break;#endif	      case 'V':		if (GET_CODE (op) == MEM		    && ! offsettable_memref_p (op))		  win = 1;		break;	      case 'o':		if ((strict > 0 && offsettable_memref_p (op))		    || (strict == 0 && offsettable_nonstrict_memref_p (op))		    /* Before reload, accept what reload can handle.  */		    || (strict < 0			&& (CONSTANT_P (op) || GET_CODE (op) == MEM))		    /* During reload, accept a pseudo  */		    || (reload_in_progress && GET_CODE (op) == REG			&& REGNO (op) >= FIRST_PSEUDO_REGISTER))		  win = 1;		break;	      default:		if (strict < 0		    || (strict == 0			&& GET_CODE (op) == REG			&& REGNO (op) >= FIRST_PSEUDO_REGISTER)		    || (strict == 0 && GET_CODE (op) == SCRATCH)		    || (GET_CODE (op) == REG			&& reg_fits_class_p (op, REG_CLASS_FROM_LETTER (c),					     offset, mode)))		  win = 1;	      }	  constraints[opno] = p;	  /* If this operand did not win somehow,	     this alternative loses.  */	  if (! win)	    lose = 1;	}      /* This alternative won; the operands are ok.	 Change whichever operands this alternative says to change.  */      if (! lose)	{	  int opno, eopno;	  /* See if any earlyclobber operand conflicts with some other	     operand.  */	  if (strict > 0)	    for (eopno = 0; eopno < noperands; eopno++)	      /* Ignore earlyclobber operands now in memory,		 because we would often report failure when we have		 two memory operands, one of which was formerly a REG.  */	      if (earlyclobber[eopno]		  && GET_CODE (recog_operand[eopno]) == REG)		for (opno = 0; opno < noperands; opno++)		  if ((GET_CODE (recog_operand[opno]) == MEM		       || op_types[opno] != OP_OUT)		      && opno != eopno		      /* Ignore things like match_operator operands. */		      && *constraints[opno] != 0		      && ! (matching_operands[opno] == eopno			    && rtx_equal_p (recog_operand[opno],					    recog_operand[eopno]))		      && ! safe_from_earlyclobber (recog_operand[opno],						   recog_operand[eopno]))		    lose = 1;	  if (! lose)	    {	      while (--funny_match_index >= 0)		{		  recog_operand[funny_match[funny_match_index].other]		    = recog_operand[funny_match[funny_match_index].this];		}	      return 1;	    }	}      which_alternative++;    }  /* If we are about to reject this, but we are not to test strictly,     try a very loose test.  Only return failure if it fails also.  */  if (strict == 0)    return constrain_operands (insn_code_num, -1);  else    return 0;}/* Return 1 iff OPERAND (assumed to be a REG rtx)   is a hard reg in class CLASS when its regno is offsetted by OFFSET   and changed to mode MODE.   If REG occupies multiple hard regs, all of them must be in CLASS.  */intreg_fits_class_p (operand, class, offset, mode)     rtx operand;     register enum reg_class class;     int offset;     enum machine_mode mode;{  register int regno = REGNO (operand);  if (regno < FIRST_PSEUDO_REGISTER      && TEST_HARD_REG_BIT (reg_class_contents[(int) class],			    regno + offset))    {      register int sr;      regno += offset;      for (sr = HARD_REGNO_NREGS (regno, mode) - 1;	   sr > 0; sr--)	if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],				 regno + sr))	  break;      return sr == 0;    }  return 0;}#endif /* REGISTER_CONSTRAINTS */

⌨️ 快捷键说明

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