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

📄 reg-stack.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
	abort ();    }  swap_rtx = gen_swapdf (FP_MODE_REG (hard_regno, DFmode),			 FP_MODE_REG (FIRST_STACK_REG, DFmode));  swap_insn = emit_insn_after (swap_rtx, i1);  /* ??? This used to be VOIDmode, but that seems wrong. */  PUT_MODE (swap_insn, QImode);}/* Handle a move to or from a stack register in PAT, which is in INSN.   REGSTACK is the current stack. */static voidmove_for_stack_reg (insn, regstack, pat)     rtx insn;     stack regstack;     rtx pat;{  rtx *psrc =  get_true_reg (&SET_SRC (pat));  rtx *pdest = get_true_reg (&SET_DEST (pat));  rtx src, dest;  rtx note;  src = *psrc; dest = *pdest;  if (STACK_REG_P (src) && STACK_REG_P (dest))    {      /* Write from one stack reg to another.  If SRC dies here, then	 just change the register mapping and delete the insn. */      note = find_regno_note (insn, REG_DEAD, REGNO (src));      if (note)	{	  int i;	  /* If this is a no-op move, there must not be a REG_DEAD note. */	  if (REGNO (src) == REGNO (dest))	    abort ();	  for (i = regstack->top; i >= 0; i--)	    if (regstack->reg[i] == REGNO (src))	      break;	  /* The source must be live, and the dest must be dead. */	  if (i < 0 || get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)	    abort ();	  /* It is possible that the dest is unused after this insn.	     If so, just pop the src. */	  if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))	    {	      emit_pop_insn (insn, regstack, src, emit_insn_after);	      delete_insn_for_stacker (insn);	      return;	    }	  regstack->reg[i] = REGNO (dest);	  SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));	  delete_insn_for_stacker (insn);	  return;	}      /* The source reg does not die. */      /* If this appears to be a no-op move, delete it, or else it	 will confuse the machine description output patterns. But if	 it is REG_UNUSED, we must pop the reg now, as per-insn processing	 for REG_UNUSED will not work for deleted insns. */      if (REGNO (src) == REGNO (dest))	{	  if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))	    emit_pop_insn (insn, regstack, dest, emit_insn_after);	  delete_insn_for_stacker (insn);	  return;	}      /* The destination ought to be dead */      if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)	abort ();      replace_reg (psrc, get_hard_regnum (regstack, src));      regstack->reg[++regstack->top] = REGNO (dest);      SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));      replace_reg (pdest, FIRST_STACK_REG);    }  else if (STACK_REG_P (src))    {      /* Save from a stack reg to MEM, or possibly integer reg.  Since	 only top of stack may be saved, emit an exchange first if	 needs be. */      emit_swap_insn (insn, regstack, src);      note = find_regno_note (insn, REG_DEAD, REGNO (src));      if (note)	{	  replace_reg (&XEXP (note, 0), FIRST_STACK_REG);	  regstack->top--;	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));	}      else if (GET_MODE (src) == XFmode && regstack->top != REG_STACK_SIZE)	{	  /* A 387 cannot write an XFmode value to a MEM without	     clobbering the source reg.  The output code can handle	     this by reading back the value from the MEM.	     But it is more efficient to use a temp register if one is	     available.  Push the source value here if the register	     stack is not full, and then write the value to memory via	     a pop.  */	  rtx push_rtx, push_insn;	  rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, XFmode);	  push_rtx = gen_movxf (top_stack_reg, top_stack_reg);	  push_insn = emit_insn_before (push_rtx, insn);	  PUT_MODE (push_insn, QImode);	  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD, top_stack_reg,				      REG_NOTES (insn));	}      replace_reg (psrc, FIRST_STACK_REG);    }  else if (STACK_REG_P (dest))    {      /* Load from MEM, or possibly integer REG or constant, into the	 stack regs.  The actual target is always the top of the	 stack. The stack mapping is changed to reflect that DEST is	 now at top of stack.  */      /* The destination ought to be dead */      if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)	abort ();      if (regstack->top >= REG_STACK_SIZE)	abort ();      regstack->reg[++regstack->top] = REGNO (dest);      SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));      replace_reg (pdest, FIRST_STACK_REG);    }  else    abort ();}voidswap_rtx_condition (pat)     rtx pat;{  register char *fmt;  register int i;  if (GET_RTX_CLASS (GET_CODE (pat)) == '<')    {      PUT_CODE (pat, swap_condition (GET_CODE (pat)));      return;    }  fmt = GET_RTX_FORMAT (GET_CODE (pat));  for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)    {      if (fmt[i] == 'E')	{	  register int j;	  for (j = XVECLEN (pat, i) - 1; j >= 0; j--)	    swap_rtx_condition (XVECEXP (pat, i, j));	}      else if (fmt[i] == 'e')	swap_rtx_condition (XEXP (pat, i));    }}/* Handle a comparison.  Special care needs to be taken to avoid   causing comparisons that a 387 cannot do correctly, such as EQ.   Also, a pop insn may need to be emitted.  The 387 does have an   `fcompp' insn that can pop two regs, but it is sometimes too expensive   to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to   set up. */static voidcompare_for_stack_reg (insn, regstack, pat)     rtx insn;     stack regstack;     rtx pat;{  rtx *src1, *src2;  rtx src1_note, src2_note;  src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));  src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));  /* ??? If fxch turns out to be cheaper than fstp, give priority to     registers that die in this insn - move those to stack top first. */  if (! STACK_REG_P (*src1)      || (STACK_REG_P (*src2)	  && get_hard_regnum (regstack, *src2) == FIRST_STACK_REG))    {      rtx temp, next;      temp = XEXP (SET_SRC (pat), 0);      XEXP (SET_SRC (pat), 0) = XEXP (SET_SRC (pat), 1);      XEXP (SET_SRC (pat), 1) = temp;      src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));      src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));      next = next_cc0_user (insn);      if (next == NULL_RTX)	abort ();      swap_rtx_condition (PATTERN (next));      INSN_CODE (next) = -1;      INSN_CODE (insn) = -1;    }  /* We will fix any death note later. */  src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));  if (STACK_REG_P (*src2))    src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));  else    src2_note = NULL_RTX;  emit_swap_insn (insn, regstack, *src1);  replace_reg (src1, FIRST_STACK_REG);  if (STACK_REG_P (*src2))    replace_reg (src2, get_hard_regnum (regstack, *src2));  if (src1_note)    {      CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (XEXP (src1_note, 0)));      replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);      regstack->top--;    }  /* If the second operand dies, handle that.  But if the operands are     the same stack register, don't bother, because only one death is     needed, and it was just handled. */  if (src2_note      && ! (STACK_REG_P (*src1) && STACK_REG_P (*src2)	    && REGNO (*src1) == REGNO (*src2)))    {      /* As a special case, two regs may die in this insn if src2 is	 next to top of stack and the top of stack also dies.  Since	 we have already popped src1, "next to top of stack" is really	 at top (FIRST_STACK_REG) now. */      if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG	  && src1_note)	{	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (XEXP (src2_note, 0)));	  replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);	  regstack->top--;	}      else	{	  /* The 386 can only represent death of the first operand in	     the case handled above.  In all other cases, emit a separate	     pop and remove the death note from here. */	  link_cc0_insns (insn);	  remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0)));	  emit_pop_insn (insn, regstack, XEXP (src2_note, 0),			 emit_insn_after);	}    }}/* Substitute new registers in PAT, which is part of INSN.  REGSTACK   is the current register layout. */static voidsubst_stack_regs_pat (insn, regstack, pat)     rtx insn;     stack regstack;     rtx pat;{  rtx *dest, *src;  rtx *src1 = (rtx *) NULL_PTR, *src2;  rtx src1_note, src2_note;  if (GET_CODE (pat) != SET)    return;  dest = get_true_reg (&SET_DEST (pat));  src  = get_true_reg (&SET_SRC (pat));  /* See if this is a `movM' pattern, and handle elsewhere if so. */  if (*dest != cc0_rtx      && (STACK_REG_P (*src)	  || (STACK_REG_P (*dest)	      && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM		  || GET_CODE (*src) == CONST_DOUBLE))))    move_for_stack_reg (insn, regstack, pat);  else    switch (GET_CODE (SET_SRC (pat)))      {      case COMPARE:	compare_for_stack_reg (insn, regstack, pat);	break;      case CALL:	 {	   int count;	   for (count = HARD_REGNO_NREGS (REGNO (*dest), GET_MODE (*dest));              --count >= 0;)	    {	      regstack->reg[++regstack->top] = REGNO (*dest) + count;	      SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count);	    }	 }	replace_reg (dest, FIRST_STACK_REG);	break;      case REG:	/* This is a `tstM2' case. */	if (*dest != cc0_rtx)	  abort ();	src1 = src;	/* Fall through. */      case FLOAT_TRUNCATE:      case SQRT:      case ABS:      case NEG:	/* These insns only operate on the top of the stack. DEST might	   be cc0_rtx if we're processing a tstM pattern. Also, it's	   possible that the tstM case results in a REG_DEAD note on the	   source.  */	if (src1 == 0)	  src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));	emit_swap_insn (insn, regstack, *src1);	src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));	if (STACK_REG_P (*dest))	  replace_reg (dest, FIRST_STACK_REG);	if (src1_note)	  {	    replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);	    regstack->top--;	    CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));	  }	replace_reg (src1, FIRST_STACK_REG);	break;      case MINUS:      case DIV:	/* On i386, reversed forms of subM3 and divM3 exist for	   MODE_FLOAT, so the same code that works for addM3 and mulM3	   can be used. */      case MULT:      case PLUS:	/* These insns can accept the top of stack as a destination	   from a stack reg or mem, or can use the top of stack as a	   source and some other stack register (possibly top of stack)	   as a destination. */	src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));	src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));	/* We will fix any death note later. */	if (STACK_REG_P (*src1))	  src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));	else	  src1_note = NULL_RTX;	if (STACK_REG_P (*src2))	  src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));	else	  src2_note = NULL_RTX;	/* If either operand is not a stack register, then the dest	   must be top of stack. */	if (! STACK_REG_P (*src1) || ! STACK_REG_P (*src2))	  emit_swap_insn (insn, regstack, *dest);	else	  {	    /* Both operands are REG.  If neither operand is already	       at the top of stack, choose to make the one that is the dest	       the new top of stack.  */	    int src1_hard_regnum, src2_hard_regnum;	    src1_hard_regnum = get_hard_regnum (regstack, *src1);	    src2_hard_regnum = get_hard_regnum (regstack, *src2);	    if (src1_hard_regnum == -1 || src2_hard_regnum == -1)	      abort ();	    if (src1_hard_regnum != FIRST_STACK_REG		&& src2_hard_regnum != FIRST_STACK_REG)	      emit_swap_insn (insn, regstack, *dest);	  }	if (STACK_REG_P (*src1))	  replace_reg (src1, get_hard_regnum (regstack, *src1));	if (STACK_REG_P (*src2))	  replace_reg (src2, get_hard_regnum (regstack, *src2));	if (src1_note)	  {	    /* If the register that dies is at the top of stack, then	       the destination is somewhere else - merely substitute it.	       But if the reg that dies is not at top of stack, then	       move the top of stack to the dead reg, as though we had	       done the insn and then a store-with-pop. */	    if (REGNO (XEXP (src1_note, 0)) == regstack->reg[regstack->top])	      {		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));		replace_reg (dest, get_hard_regnum (regstack, *dest));	      }	    else	      {		int regno = get_hard_regnum (regstack, XEXP (src1_note, 0));		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));		replace_reg (dest, regno);		regstack->reg[regstack->top - (regno - FIRST_STACK_REG)]		  = regst

⌨️ 快捷键说明

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