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

📄 rs6000.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  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);  for (i = 1; i < count; i++)    {      rtx elt = XVECEXP (op, 0, i + 1);      if (GET_CODE (elt) != SET	  || GET_CODE (SET_SRC (elt)) != REG	  || GET_MODE (SET_SRC (elt)) != SImode	  || REGNO (SET_SRC (elt)) != src_regno + i	  || GET_CODE (SET_DEST (elt)) != MEM	  || GET_MODE (SET_DEST (elt)) != SImode	  || 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)) != i * 4)	return 0;    }  return 1;}/* Return 1 if OP is a comparison operation that is valid for a branch insn.   We only check the opcode against the mode of the CC value here.  */intbranch_comparison_operator (op, mode)     register rtx op;     enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  enum machine_mode cc_mode;  if (GET_RTX_CLASS (code) != '<')    return 0;  cc_mode = GET_MODE (XEXP (op, 0));  if (GET_MODE_CLASS (cc_mode) != MODE_CC)    return 0;  if ((code == GT || code == LT || code == GE || code == LE)      && cc_mode == CCUNSmode)    return 0;  if ((code == GTU || code == LTU || code == GEU || code == LEU)      && (cc_mode != CCUNSmode))    return 0;  return 1;}/* Return 1 if OP is a comparison operation that is valid for an scc insn.   We check the opcode against the mode of the CC value and disallow EQ or   NE comparisons for integers.  */intscc_comparison_operator (op, mode)     register rtx op;     enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  enum machine_mode cc_mode;  if (GET_MODE (op) != mode && mode != VOIDmode)    return 0;  if (GET_RTX_CLASS (code) != '<')    return 0;  cc_mode = GET_MODE (XEXP (op, 0));  if (GET_MODE_CLASS (cc_mode) != MODE_CC)    return 0;  if (code == NE && cc_mode != CCFPmode)    return 0;  if ((code == GT || code == LT || code == GE || code == LE)      && cc_mode == CCUNSmode)    return 0;  if ((code == GTU || code == LTU || code == GEU || code == LEU)      && (cc_mode != CCUNSmode))    return 0;  if (cc_mode == CCEQmode && code != EQ && code != NE)    return 0;  return 1;}/* Return 1 if ANDOP is a mask that has no bits on that are not in the   mask required to convert the result of a rotate insn into a shift   left insn of SHIFTOP bits.  Both are known to be CONST_INT.  */intincludes_lshift_p (shiftop, andop)     register rtx shiftop;     register rtx andop;{  int shift_mask = (~0 << INTVAL (shiftop));  return (INTVAL (andop) & ~shift_mask) == 0;}/* Similar, but for right shift.  */intincludes_rshift_p (shiftop, andop)     register rtx shiftop;     register rtx andop;{  unsigned shift_mask = ~0;  shift_mask >>= INTVAL (shiftop);  return (INTVAL (andop) & ~ shift_mask) == 0;}/* Return 1 if REGNO (reg1) == REGNO (reg2) - 1 making them candidates   for lfq and stfq insns.   Note reg1 and reg2 *must* be hard registers.  To be sure we will   abort if we are passed pseudo registers.  */intregisters_ok_for_quad_peep (reg1, reg2)     rtx reg1, reg2;{  /* We might have been passed a SUBREG.  */  if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)     return 0;  return (REGNO (reg1) == REGNO (reg2) - 1);}/* Return 1 if addr1 and addr2 are suitable for lfq or stfq insn.  addr1 and   addr2 must be in consecutive memory locations (addr2 == addr1 + 8).  */intaddrs_ok_for_quad_peep (addr1, addr2)     register rtx addr1;     register rtx addr2;{  int reg1;  int offset1;  /* Extract an offset (if used) from the first addr.  */  if (GET_CODE (addr1) == PLUS)    {      /* If not a REG, return zero.  */      if (GET_CODE (XEXP (addr1, 0)) != REG)	return 0;      else	{          reg1 = REGNO (XEXP (addr1, 0));	  /* The offset must be constant!  */	  if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)            return 0;          offset1 = INTVAL (XEXP (addr1, 1));	}    }  else if (GET_CODE (addr1) != REG)    return 0;  else    {      reg1 = REGNO (addr1);      /* This was a simple (mem (reg)) expression.  Offset is 0.  */      offset1 = 0;    }  /* Make sure the second address is a (mem (plus (reg) (const_int).  */  if (GET_CODE (addr2) != PLUS)    return 0;  if (GET_CODE (XEXP (addr2, 0)) != REG      || GET_CODE (XEXP (addr2, 1)) != CONST_INT)    return 0;  if (reg1 != REGNO (XEXP (addr2, 0)))    return 0;  /* The offset for the second addr must be 8 more than the first addr.  */  if (INTVAL (XEXP (addr2, 1)) != offset1 + 8)    return 0;  /* All the tests passed.  addr1 and addr2 are valid for lfq or stfq     instructions.  */  return 1;}/* Return the register class of a scratch register needed to copy IN into   or out of a register in CLASS in MODE.  If it can be done directly,   NO_REGS is returned.  */enum reg_classsecondary_reload_class (class, mode, in)     enum reg_class class;     enum machine_mode mode;     rtx in;{  int regno = true_regnum (in);  if (regno >= FIRST_PSEUDO_REGISTER)    regno = -1;  /* We can place anything into GENERAL_REGS and can put GENERAL_REGS     into anything.  */  if (class == GENERAL_REGS || class == BASE_REGS      || (regno >= 0 && INT_REGNO_P (regno)))    return NO_REGS;  /* Constants, memory, and FP registers can go into FP registers.  */  if ((regno == -1 || FP_REGNO_P (regno))      && (class == FLOAT_REGS || class == NON_SPECIAL_REGS))    return NO_REGS;  /* We can copy among the CR registers.  */  if ((class == CR_REGS || class == CR0_REGS)      && regno >= 0 && CR_REGNO_P (regno))    return NO_REGS;  /* Otherwise, we need GENERAL_REGS.  */  return GENERAL_REGS;}/* Given a comparison operation, return the bit number in CCR to test.  We   know this is a valid comparison.     SCC_P is 1 if this is for an scc.  That means that %D will have been   used instead of %C, so the bits will be in different places.   Return -1 if OP isn't a valid comparison for some reason.  */intccr_bit (op, scc_p)     register rtx op;     int scc_p;{  enum rtx_code code = GET_CODE (op);  enum machine_mode cc_mode;  int cc_regnum;  int base_bit;  if (GET_RTX_CLASS (code) != '<')    return -1;  cc_mode = GET_MODE (XEXP (op, 0));  cc_regnum = REGNO (XEXP (op, 0));  base_bit = 4 * (cc_regnum - 68);  /* In CCEQmode cases we have made sure that the result is always in the     third bit of the CR field.  */  if (cc_mode == CCEQmode)    return base_bit + 3;  switch (code)    {    case NE:      return scc_p ? base_bit + 3 : base_bit + 2;    case EQ:      return base_bit + 2;    case GT:  case GTU:      return base_bit + 1;    case LT:  case LTU:      return base_bit;    case GE:  case GEU:      /* If floating-point, we will have done a cror to put the bit in the	 unordered position.  So test that bit.  For integer, this is ! LT	 unless this is an scc insn.  */      return cc_mode == CCFPmode || scc_p ? base_bit + 3 : base_bit;    case LE:  case LEU:      return cc_mode == CCFPmode || scc_p ? base_bit + 3 : base_bit + 1;    default:      abort ();    }}/* Print an operand.  Recognize special options, documented below.  */voidprint_operand (file, x, code)    FILE *file;    rtx x;    char code;{  int i;  int val;  /* These macros test for integers and extract the low-order bits.  */#define INT_P(X)  \((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE)	\ && GET_MODE (X) == VOIDmode)#define INT_LOWPART(X) \  (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))  switch (code)    {    case '.':      /* Write out an instruction after the call which may be replaced	 with glue code by the loader.  This depends on the AIX version.  */      asm_fprintf (file, RS6000_CALL_GLUE);      return;    case '*':      /* Write the register number of the TOC register.  */      fputs (TARGET_MINIMAL_TOC ? reg_names[30] : reg_names[2], file);      return;    case 'A':      /* If X is a constant integer whose low-order 5 bits are zero,	 write 'l'.  Otherwise, write 'r'.  This is a kludge to fix a bug	 in the AIX assembler where "sri" with a zero shift count	 write a trash instruction.  */      if (GET_CODE (x) == CONST_INT && (INTVAL (x) & 31) == 0)	putc ('l', file);      else	putc ('r', file);      return;    case 'b':      /* Low-order 16 bits of constant, unsigned.  */      if (! INT_P (x))	output_operand_lossage ("invalid %%b value");      fprintf (file, "%d", INT_LOWPART (x) & 0xffff);      return;    case 'C':      /* This is an optional cror needed for LE or GE floating-point	 comparisons.  Otherwise write nothing.  */      if ((GET_CODE (x) == LE || GET_CODE (x) == GE)	  && GET_MODE (XEXP (x, 0)) == CCFPmode)	{	  int base_bit = 4 * (REGNO (XEXP (x, 0)) - 68);	  fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3,		   base_bit + 2, base_bit + (GET_CODE (x) == GE));	}      return;    case 'D':      /* Similar, except that this is for an scc, so we must be able to	 encode the test in a single bit that is one.  We do the above	 for any LE, GE, GEU, or LEU and invert the bit for NE.  */      if (GET_CODE (x) == LE || GET_CODE (x) == GE	  || GET_CODE (x) == LEU || GET_CODE (x) == GEU)	{	  int base_bit = 4 * (REGNO (XEXP (x, 0)) - 68);	  fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3,		   base_bit + 2,		   base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU));	}      else if (GET_CODE (x) == NE)	{	  int base_bit = 4 * (REGNO (XEXP (x, 0)) - 68);	  fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3,		   base_bit + 2, base_bit + 2);	}      return;    case 'E':      /* X is a CR register.  Print the number of the third bit of the CR */      if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))	output_operand_lossage ("invalid %%E value");      fprintf(file, "%d", 4 * (REGNO (x) - 68) + 3);      return;    case 'f':      /* X is a CR register.  Print the shift count needed to move it	 to the high-order four bits.  */      if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))	output_operand_lossage ("invalid %%f value");      else	fprintf (file, "%d", 4 * (REGNO (x) - 68));      return;    case 'F':      /* Similar, but print the count for the rotate in the opposite	 direction.  */      if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))	output_operand_lossage ("invalid %%F value");      else	fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68));      return;    case 'G':      /* X is a constant integer.  If it is negative, print "m",	 otherwise print "z".  This is to make a aze or ame insn.  */      if (GET_CODE (x) != CONST_INT)	output_operand_lossage ("invalid %%G value");      else if (INTVAL (x) >= 0)	putc ('z', file);      else	putc ('m', file);      return;	    case 'h':      /* If constant, output low-order five bits.  Otherwise,	 write normally. */      if (INT_P (x))	fprintf (file, "%d", INT_LOWPART (x) & 31);      else	print_operand (file, x, 0);      return;    case 'I':      /* Print `i' if this is a constant, else nothing.  */      if (INT_P (x))	putc ('i', file);      return;    case 'j':      /* Write the bit number in CCR for jump.  */      i = ccr_bit (x, 0);      if (i == -1)	output_operand_lossage ("invalid %%j code");      else	fprintf (file, "%d", i);      return;    case 'J':      /* Similar, but add one for shift count in rlinm for scc and pass	 scc flag to `ccr_bit'.  */      i = ccr_bit (x, 1);      if (i == -1)	output_operand_lossage ("invalid %%J code");      else	/* If we want bit 31, write a shift count of zero, not 32.  */	fprintf (file, "%d", i == 31 ? 0 : i + 1);      return;    case 'k':      /* X must be a constant.  Write the 1's complement of the	 constant.  */      if (! INT_P (x))	output_operand_lossage ("invalid %%k value");      fprintf (file, "%d", ~ INT_LOWPART (x));      return;    case 'L':      /* Write second word of DImode or DFmode reference.  Works on register	 or non-indexed memory only.  */      if (GET_CODE (x) == REG)	fprintf (file, "%d", REGNO (x) + 1);      else if (GET_CODE (x) == MEM)	{	  /* Handle possible auto-increment.  Since it is pre-increment and	     we have already done it, we can just use an offset of four.  */	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));	  else	    output_address (plus_constant (XEXP (x, 0), 4));	}      return;			        case 'm':      /* MB value for a mask operand.  */      if (! mask_operand (x, VOIDmode))	output_operand_lossage ("invalid %%m value");      val = INT_LOWPART (x);

⌨️ 快捷键说明

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