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

📄 rs6000.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  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 HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 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 ();    }}/* Return the GOT register, creating it if needed.  */struct rtx_def *rs6000_got_register (value)     rtx value;{  if (!current_function_uses_pic_offset_table || !pic_offset_table_rtx)    {      if (reload_in_progress || reload_completed)	fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value);      current_function_uses_pic_offset_table = 1;      pic_offset_table_rtx = gen_rtx (REG, Pmode, GOT_TOC_REGNUM);    }  return pic_offset_table_rtx;}/* Replace all occurrences of register FROM with an new pseudo register in an insn X.   Store the pseudo register used in REG.   This is only safe during FINALIZE_PIC, since the registers haven't been setup   yet.  */static rtxrs6000_replace_regno (x, from, reg)     rtx x;     int from;     rtx *reg;{  register int i, j;  register char *fmt;  /* Allow this function to make replacements in EXPR_LISTs.  */  if (!x)    return x;  switch (GET_CODE (x))    {    case SCRATCH:    case PC:    case CC0:    case CONST_INT:    case CONST_DOUBLE:    case CONST:    case SYMBOL_REF:    case LABEL_REF:      return x;    case REG:      if (REGNO (x) == from)	{	  if (! *reg)	    *reg = pic_offset_table_rtx = gen_reg_rtx (Pmode);	  return *reg;	}      return x;    }  fmt = GET_RTX_FORMAT (GET_CODE (x));  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	XEXP (x, i) = rs6000_replace_regno (XEXP (x, i), from, reg);      else if (fmt[i] == 'E')	for (j = XVECLEN (x, i) - 1; j >= 0; j--)	  XVECEXP (x, i, j) = rs6000_replace_regno (XVECEXP (x, i, j), from, reg);    }  return x;}  /* By generating position-independent code, when two different   programs (A and B) share a common library (libC.a), the text of   the library can be shared whether or not the library is linked at   the same address for both programs.  In some of these   environments, position-independent code requires not only the use   of different addressing modes, but also special code to enable the   use of these addressing modes.   The `FINALIZE_PIC' macro serves as a hook to emit these special   codes once the function is being compiled into assembly code, but   not before.  (It is not done before, because in the case of   compiling an inline function, it would lead to multiple PIC   prologues being included in functions which used inline functions   and were compiled to assembly language.)  */voidrs6000_finalize_pic (){  /* Loop through all of the insns, replacing the special GOT_TOC_REGNUM     with an appropriate pseudo register.  If we find we need GOT/TOC,     add the appropriate init code.  */  if (flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))    {      rtx insn = get_insns ();      rtx reg = NULL_RTX;      rtx first_insn;      rtx last_insn = NULL_RTX;      if (GET_CODE (insn) == NOTE)	insn = next_nonnote_insn (insn);      first_insn = insn;      for ( ; insn != NULL_RTX; insn = NEXT_INSN (insn))	{	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')	    {	      PATTERN (insn) = rs6000_replace_regno (PATTERN (insn),						     GOT_TOC_REGNUM,						     &reg);	      if (REG_NOTES (insn))		REG_NOTES (insn) = rs6000_replace_regno (REG_NOTES (insn),							 GOT_TOC_REGNUM,							 &reg);	    }	  if (GET_CODE (insn) != NOTE)	    last_insn = insn;	}      if (reg)	{	  rtx init = gen_init_v4_pic (reg);	  emit_insn_before (init, first_insn);	  if (!optimize && last_insn)	    emit_insn_after (gen_rtx (USE, VOIDmode, reg), last_insn);	}    }}/* Search for any occurrence of the GOT_TOC register marker that should   have been eliminated, but may have crept back in.  */voidrs6000_reorg (insn)     rtx insn;{  if (flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))    {      rtx got_reg = gen_rtx (REG, Pmode, GOT_TOC_REGNUM);      for ( ; insn != NULL_RTX; insn = NEXT_INSN (insn))	if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'	    && reg_mentioned_p (got_reg, PATTERN (insn)))	  fatal_insn ("GOT/TOC register marker not removed:", PATTERN (insn));    }}/* Define the structure for the machine field in struct function.  */struct machine_function{  int sysv_varargs_p;  int save_toc_p;  int fpmem_size;  int fpmem_offset;  rtx pic_offset_table_rtx;};/* Functions to save and restore rs6000_fpmem_size.   These will be called, via pointer variables,   from push_function_context and pop_function_context.  */voidrs6000_save_machine_status (p)     struct function *p;{  struct machine_function *machine =    (struct machine_function *) xmalloc (sizeof (struct machine_function));  p->machine = machine;  machine->sysv_varargs_p = rs6000_sysv_varargs_p;  machine->fpmem_size     = rs6000_fpmem_size;  machine->fpmem_offset   = rs6000_fpmem_offset;  machine->pic_offset_table_rtx = pic_offset_table_rtx;}voidrs6000_restore_machine_status (p)     struct function *p;{  struct machine_function *machine = p->machine;  rs6000_sysv_varargs_p = machine->sysv_varargs_p;  rs6000_fpmem_size     = machine->fpmem_size;  rs6000_fpmem_offset   = machine->fpmem_offset;  pic_offset_table_rtx  = machine->pic_offset_table_rtx;  free (machine);  p->machine = (struct machine_function *)0;}/* Do anything needed before RTL is emitted for each function.  */voidrs6000_init_expanders (){  /* Reset varargs and save TOC indicator */  rs6000_sysv_varargs_p = 0;  rs6000_fpmem_size = 0;  rs6000_fpmem_offset = 0;  pic_offset_table_rtx = (rtx)0;  /* Arrange to save and restore machine status aro

⌨️ 快捷键说明

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