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

📄 reg-stack.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* 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 = 0, *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:	regstack->reg[++regstack->top] = REGNO (*dest);	SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));	replace_reg (dest, FIRST_STACK_REG);	break;      case REG:	/* This is a `tstM2' case. */	if (*dest != cc0_rtx)	  abort ();	src1 = src;	/* Fall through. */      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, emit_insn_before);	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 = 0;	if (STACK_REG_P (*src2))	  src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));	else	  src2_note = 0;	/* 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, emit_insn_before);	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.	       ??? A later optimization here would be to look forward	       in the insns and see which source reg will be needed at top	       of stack soonest. */	    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, emit_insn_before);	  }	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)]		  = regstack->reg[regstack->top];	      }	    CLEAR_HARD_REG_BIT (regstack->reg_set,				REGNO (XEXP (src1_note, 0)));	    replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);	    regstack->top--;	  }	else if (src2_note)	  {	    if (REGNO (XEXP (src2_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 (src2_note, 0));		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));		replace_reg (dest, regno);		regstack->reg[regstack->top - (regno - FIRST_STACK_REG)]		  = regstack->reg[regstack->top];	      }	    CLEAR_HARD_REG_BIT (regstack->reg_set,				REGNO (XEXP (src2_note, 0)));	    replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG);	    regstack->top--;	  }	else	  {	    SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));	    replace_reg (dest, get_hard_regnum (regstack, *dest));	  }	break;      case UNSPEC:	switch (XINT (SET_SRC (pat), 1))	  {	  case 1: /* sin */	  case 2: /* cos */	    /* These insns only operate on the top of the stack.  */	    src1 = get_true_reg (&XVECEXP (SET_SRC (pat), 0, 0));	    emit_swap_insn (insn, regstack, *src1, emit_insn_before);	    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;	  default:	    abort ();	  }	break;      default:	abort ();      }}/* Substitute hard regnums for any stack regs in INSN, which has   N_INPUTS inputs and N_OUTPUTS outputs.  REGSTACK is the stack info   before the insn, and is updated with changes made here.  CONSTRAINTS is   an array of the constraint strings used in the asm statement.   OPERANDS is an array of the operands, and OPERANDS_LOC is a   parallel array of where the operands were found.  The output operands   all precede the input operands.   There are several requirements and assumptions about the use of   stack-like regs in asm statements.  These rules are enforced by   record_asm_stack_regs; see comments there for details.  Any   asm_operands left in the RTL at this point may be assume to meet the   requirements, since record_asm_stack_regs removes any problem asm.  */static voidsubst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,		      n_inputs, n_outputs)     rtx insn;     stack regstack;     rtx *operands, **operands_loc;     char **constraints;     int n_inputs, n_outputs;{  int n_operands = n_inputs + n_outputs;  int first_input = n_outputs;  rtx body = PATTERN (insn);  int *operand_matches = (int *) alloca (n_operands * sizeof (int *));  enum reg_class *operand_class     = (enum reg_class *) alloca (n_operands * sizeof (enum reg_class *));  rtx *note_reg;		/* Array of note contents */  rtx **note_loc;		/* Address of REG field of each note */  enum reg_note *note_kind;	/* The type of each note */  rtx *clobber_reg;  rtx **clobber_loc;  struct stack_def temp_stack;  int n_notes;  int n_clobbers;  rtx note;  int i;  /* Find out what the constraints required.  If no constraint     alternative matches, that is a compiler bug: we should have caught     such an insn during the life analysis pass (and reload should have     caught it regardless). */  i = constrain_asm_operands (n_operands, operands, constraints,			      operand_matches, operand_class);  if (i < 0)    abort ();  /* Strip SUBREGs here to make the following code simpler. */  for (i = 0; i < n_operands; i++)    if (GET_CODE (operands[i]) == SUBREG	&& GET_CODE (SUBREG_REG (operands[i])) == REG)      {	operands_loc[i] = & SUBREG_REG (operands[i]);	operands[i] = SUBREG_REG (operands[i]);      }  /* Set up NOTE_REG, NOTE_LOC and NOTE_KIND.  */  for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1))    i++;  note_reg = (rtx *) alloca (i * sizeof (rtx));  note_loc = (rtx **) alloca (i * sizeof (rtx *));  note_kind = (enum reg_note *) alloca (i * sizeof (enum reg_note));  n_notes = 0;  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))    {      rtx reg = XEXP (note, 0);      rtx *loc = & XEXP (note, 0);      if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)	{	  loc = & SUBREG_REG (reg);	  reg = SUBREG_REG (reg);	}      if (STACK_REG_P (reg)	  && (REG_NOTE_KIND (note) == REG_DEAD	      || REG_NOTE_KIND (note) == REG_UNUSED))	{	  note_reg[n_notes] = reg;	  note_loc[n_notes] = loc;	  note_kind[n_notes] = REG_NOTE_KIND (note);	  n_notes++;	}    }  /* Set up CLOBBER_REG and CLOBBER_LOC.  */  n_clobbers = 0;  if (GET_CODE (body) == PARALLEL)    {      clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx *));      clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx **));      for (i = 0; i < XVECLEN (body, 0); i++)	if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)	  {	    rtx clobber = XVECEXP (body, 0, i);	    rtx reg = XEXP (clobber, 0);	    rtx *loc = & XEXP (clobber, 0);	    if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)	      {		loc = & SUBREG_REG (reg);		reg = SUBREG_REG (reg);	      }	    if (STACK_REG_P (reg))	      {		clobber_reg[n_clobbers] = reg;		clobber_loc[n_clobbers] = loc;		n_clobbers++;	      }	  }    }  bcopy (regstack, &temp_stack, sizeof (temp_stack));  /* Put the input regs into the desired place in TEMP_STACK.  */  for (i = first_input; i < first_input + n_inputs; i++)    if (STACK_REG_P (operands[i])	&& reg_class_subset_p (operand_class[i], FLOAT_REGS)	&& operand_class[i] != FLOAT_REGS)      {	/* If an operand needs to be in a particular reg in	   FLOAT_REGS, the constraint was either 't' or 'u'.  Since	   these constraints are for single register classes, and reload	   guaranteed that operand[i] is already in that class, we can	   just use REGNO (operands[i]) to know which actual reg this	   operand needs to be in. */	int regno = get_hard_regnum (&temp_stack, operands[i]);	if (regno < 0)	  abort ();	if (regno != REGNO (operands[i]))	  {	    /* operands[i] is not in the right place.  Find it	       and swap it with whatever is already in I's place.	       K is where operands[i] is now.  J is where it should	       be. */	    int j, k, temp;	    k = temp_stack.top - (regno - FIRST_STACK_REG);	    j = (temp_stack.top		 - (REGNO (operands[i]) - FIRST_STACK_REG));	    temp = temp_stack.reg[k];	    temp_stack.reg[k] = temp_stack.reg[j];	    temp_stack.reg[j] = temp;	  }      }  /* emit insns before INSN to make sure the reg-stack is in the right     order.  */  change_stack (insn, regstack, &temp_stack, emit_insn_before);  /* Make the needed input register substitutions.  Do death notes and     clobbers too, because these are for inputs, not outputs. */  for (i = first_input; i < first_input + n_inputs; i++)    if (STACK_REG_P (operands[i]))      {	int regnum = get_hard_regnum (regstack, operands[i]);	if (regnum < 0)	  abort ();	replace_reg (operands_loc[i], regnum);      }  for (i = 0; i < n_notes; i++)    if (note_kind[i] == REG_DEAD)      {	int regnum = get_hard_regnum (regstack, note_reg[i]);	if (regnum < 0)	  abort ();	replace_reg (note_loc[i], regnum);      }  for (i = 0; i < n_clobbers; i++)    {      /* It's OK for a CLOBBER to reference a reg that is not live.         Don't try to replace it in that case.  */      int regnum = get_hard_regnum (regstack, clobber_reg[i]);      if (regnum >= 0)	{	  /* Sigh - clobbers always have QImode.  But replace_reg knows	     that these regs can't be MODE_INT and will abort.  Just p

⌨️ 快捷键说明

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