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

📄 out-i860.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
     rtx *operands;{  enum machine_mode mode = GET_MODE (operands[0]);  rtx address = XEXP (operands[1], 0);  /* We don't bother trying to see if we know %hi(address).     This is because we are doing a load, and if we know the     %hi value, we probably also know that value in memory.  */  cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;  cc_status.mdep = address;  if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)	 && (cc_prev_status.flags & CC_HI_R31_ADJ)	 && address == cc_prev_status.mdep	 && cc_prev_status.mdep == cc_status.mdep))    {      output_asm_insn ("orh ha%%%m1,r0,r31", operands);      cc_prev_status.mdep = address;    }  /* Code below isn't smart enough to move a doubleword in two parts,     so use output_move_double to do that in the cases that require it.  */  if ((mode == DImode || mode == DFmode)      && ! FP_REG_P (operands[0]))    return output_move_double (operands);  return load_opcode (mode, "l%%%m1(r31),%0", operands[0]);}#if 0/* Load the address specified by OPERANDS[3] into the register   specified by OPERANDS[0].   OPERANDS[3] may be the result of a sum, hence it could either be:   (1) CONST   (2) REG   (2) REG + CONST_INT   (3) REG + REG + CONST_INT   (4) REG + REG  (special case of 3).   Note that (3) is not a legitimate address.   All cases are handled here.  */voidoutput_load_address (operands)     rtx *operands;{  rtx base, offset;  if (CONSTANT_P (operands[3]))    {      output_asm_insn ("mov %3,%0", operands);      return;    }  if (REG_P (operands[3]))    {      if (REGNO (operands[0]) != REGNO (operands[3]))	output_asm_insn ("mov %3,%0", operands);      return;    }  if (GET_CODE (operands[3]) != PLUS)    abort ();  base = XEXP (operands[3], 0);  offset = XEXP (operands[3], 1);  if (GET_CODE (base) == CONST_INT)    {      rtx tmp = base;      base = offset;      offset = tmp;    }  if (GET_CODE (offset) != CONST_INT)    {      /* Operand is (PLUS (REG) (REG)).  */      base = operands[3];      offset = const0_rtx;    }  if (REG_P (base))    {      operands[6] = base;      operands[7] = offset;      if (SMALL_INT (offset))	output_asm_insn ("adds %7,%6,%0", operands);      else	output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);    }  else if (GET_CODE (base) == PLUS)    {      operands[6] = XEXP (base, 0);      operands[7] = XEXP (base, 1);      operands[8] = offset;      if (SMALL_INT (offset))	output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);      else	output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);    }  else    abort ();}#endif/* Output code to place a size count SIZE in register REG.  */static voidoutput_size_for_block_move (size, reg, align)     rtx size, reg, align;{  rtx xoperands[3];  xoperands[0] = reg;  xoperands[1] = size;  xoperands[2] = align;#if 1  cc_status.flags &= ~ CC_KNOW_HI_R31;  output_asm_insn ("mov %1,%0", xoperands);#else  if (GET_CODE (size) == REG)    output_asm_insn ("sub %2,%1,%0", xoperands);  else    {      xoperands[1]	= gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));      cc_status.flags &= ~ CC_KNOW_HI_R31;      output_asm_insn ("mov %1,%0", xoperands);    }#endif}/* Emit code to perform a block move.   OPERANDS[0] is the destination.   OPERANDS[1] is the source.   OPERANDS[2] is the size.   OPERANDS[3] is the known safe alignment.   OPERANDS[4..6] are pseudos we can safely clobber as temps.  */char *output_block_move (operands)     rtx *operands;{  /* A vector for our computed operands.  Note that load_output_address     makes use of (and can clobber) up to the 8th element of this vector.  */  rtx xoperands[10];  rtx zoperands[10];  static int movstrsi_label = 0;  int i, j;  rtx temp1 = operands[4];  rtx alignrtx = operands[3];  int align = INTVAL (alignrtx);  xoperands[0] = operands[0];  xoperands[1] = operands[1];  xoperands[2] = temp1;  /* We can't move more than four bytes at a time     because we have only one register to move them through.  */  if (align > 4)    {      align = 4;      alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);    }  /* Since we clobber untold things, nix the condition codes.  */  CC_STATUS_INIT;  /* Recognize special cases of block moves.  These occur     when GNU C++ is forced to treat something as BLKmode     to keep it in memory, when its mode could be represented     with something smaller.     We cannot do this for global variables, since we don't know     what pages they don't cross.  Sigh.  */  if (GET_CODE (operands[2]) == CONST_INT      && INTVAL (operands[2]) <= 16      && ! CONSTANT_ADDRESS_P (operands[0])      && ! CONSTANT_ADDRESS_P (operands[1]))    {      int size = INTVAL (operands[2]);      rtx op0 = xoperands[0];      rtx op1 = xoperands[1];      cc_status.flags &= ~CC_KNOW_HI_R31;      if (align == 1)	{	  if (memory_address_p (QImode, plus_constant (op0, size))	      && memory_address_p (QImode, plus_constant (op1, size)))	    {	      for (i = size-1; i >= 0; i--)		{		  xoperands[0] = plus_constant (op0, i);		  xoperands[1] = plus_constant (op1, i);		  output_asm_insn ("ld.b %a1,r31\n\tst.b r31,%a0",				   xoperands);		}	      return "";	    }	}      else if (align == 2)	{	  if (memory_address_p (HImode, plus_constant (op0, size))	      && memory_address_p (HImode, plus_constant (op1, size)))	    {	      for (i = (size>>1)-1; i >= 0; i--)		{		  xoperands[0] = plus_constant (op0, i * 2);		  xoperands[1] = plus_constant (op1, i * 2);		  output_asm_insn ("ld.s %a1,r31\n\tst.s r31,%a0",				   xoperands);		}	      return "";	    }	}      else	{	  if (memory_address_p (SImode, plus_constant (op0, size))	      && memory_address_p (SImode, plus_constant (op1, size)))	    {	      for (i = (size>>2)-1; i >= 0; i--)		{		  xoperands[0] = plus_constant (op0, i * 4);		  xoperands[1] = plus_constant (op1, i * 4);		  output_asm_insn ("ld.l %a1,r31\n\tst.l r31,%a0",				   xoperands);		}	      return "";	    }	}    }  /* This is the size of the transfer.     Either use the register which already contains the size,     or use a free register (used by no operands).  */  output_size_for_block_move (operands[2], operands[4], alignrtx);#if 0  /* Also emit code to decrement the size value by ALIGN.  */  zoperands[0] = operands[0];  zoperands[3] = plus_constant (operands[0], align);  output_load_address (zoperands);#endif  /* Generate number for unique label.  */  xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);  /* Copy the increment (negative) to a register for bla insn.  */  xoperands[4] = gen_rtx (CONST_INT, VOIDmode, - align);  xoperands[5] = operands[5];  output_asm_insn ("mov %4,%5", xoperands);  /* Make available a register which is a temporary.  */  xoperands[6] = operands[6];  /* Now the actual loop.     In xoperands, elements 1 and 0 are the input and output vectors.     Element 2 is the loop index.  Element 5 is the increment.  */  if (align == 1)    {      output_asm_insn ("bla %5,%2,.Lm%3", xoperands);      output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);      xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);      output_asm_insn ("adds %1,%2,%1", xoperands);      output_asm_insn ("adds %5,%2,%2\n.Lm%3:",  xoperands);      output_asm_insn ("ld.b 0(%1),r31", xoperands);      output_asm_insn ("adds %5,%1,%1", xoperands);      output_asm_insn ("st.b r31,0(%6)", xoperands);      output_asm_insn ("bla %5,%2,.Lm%3", xoperands);      output_asm_insn ("adds %5,%6,%6", xoperands);    }  if (align == 2)    {      output_asm_insn ("bla %5,%2,.Lm%3", xoperands);      output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);      xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);      output_asm_insn ("adds %1,%2,%1", xoperands);      output_asm_insn ("adds %5,%2,%2\n.Lm%3:",  xoperands);      output_asm_insn ("ld.s 0(%1),r31", xoperands);      output_asm_insn ("adds %5,%1,%1", xoperands);      output_asm_insn ("st.s r31,0(%6)", xoperands);      output_asm_insn ("bla %5,%2,.Lm%3", xoperands);      output_asm_insn ("adds %5,%6,%6", xoperands);    }  if (align == 4)    {      output_asm_insn ("bla %5,%2,.Lm%3", xoperands);      output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);      xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);      output_asm_insn ("adds %1,%2,%1", xoperands);      output_asm_insn ("adds %5,%2,%2\n.Lm%3:",  xoperands);      output_asm_insn ("ld.l 0(%1),r31", xoperands);      output_asm_insn ("adds %5,%1,%1", xoperands);      output_asm_insn ("st.l r31,0(%6)", xoperands);      output_asm_insn ("bla %5,%2,.Lm%3", xoperands);      output_asm_insn ("adds %5,%6,%6", xoperands);    }  return "";}/* Output a delayed branch insn with the delay insn in its   branch slot.  The delayed branch insn template is in TEMPLATE,   with operands OPERANDS.  The insn in its delay slot is INSN.   As a special case, since we know that all memory transfers are via   ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory   reference around the branch as	orh ha%x,r0,r31	b ...	ld/st l%x(r31),...   As another special case, we handle loading (SYMBOL_REF ...) and   other large constants around branches as well:	orh h%x,r0,%0	b ...	or l%x,%0,%1   */char *output_delayed_branch (template, operands, insn)     char *template;     rtx *operands;     rtx insn;{  extern rtx recog_operand[];  rtx src = XVECEXP (PATTERN (insn), 0, 1);  rtx dest = XVECEXP (PATTERN (insn), 0, 0);  if (GET_CODE (src) == SYMBOL_REF || GET_CODE (src) == CONST      || (GET_CODE (src) == CONST_INT	  && !(SMALL_INT (src) || (INTVAL (src) & 0xffff) == 0)))    {      rtx xoperands[2];      xoperands[0] = dest;      xoperands[1] = src;      /* Output the `orh' insn.  */      output_asm_insn ("orh h%%%1,r0,%0", xoperands);      /* Output the branch instruction next.  */      output_asm_insn (template, operands);      /* Now output the `or' insn.  */      output_asm_insn ("or l%%%1,%0,%0", xoperands);    }  else if ((GET_CODE (src) == MEM	    && CONSTANT_ADDRESS_P (XEXP (src, 0)))	   || (GET_CODE (dest) == MEM	       && CONSTANT_ADDRESS_P (XEXP (dest, 0))))    {      rtx xoperands[2];      char *split_template;      xoperands[0] = dest;      xoperands[1] = src;      /* Output the `orh' insn.  */      if (GET_CODE (src) == MEM)	{	  if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)		 && (cc_prev_status.flags & CC_HI_R31_ADJ)		 && cc_prev_status.mdep == XEXP (operands[1], 0)))	    output_asm_insn ("orh ha%%%m1,r0,r31", xoperands);	  split_template = load_opcode (GET_MODE (dest),					"l%%%m1(r31),%0", dest);	}      else	{	  if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)		 && (cc_prev_status.flags & CC_HI_R31_ADJ)		 && cc_prev_status.mdep == XEXP (operands[0], 0)))	    output_asm_insn ("orh ha%%%m0,r0,r31", xoperands);	  split_template = store_opcode (GET_MODE (dest),					 "%r1,l%%%m0(r31)", src);	}      /* Output the branch instruction next.  */      output_asm_insn (template, operands);      /* Now output the load or store.	 No need to do a CC_STATUS_INIT, because we are branching anyway.  */      output_asm_insn (split_template, xoperands);    }  else    {      extern char *insn_template[];      extern char *(*insn_outfun[])();      extern int insn_n_operands[];      extern rtx alter_subreg();      int insn_code_number;      rtx pat = gen_rtx (SET, VOIDmode, dest, src);      rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);      int i;      /* Output the branch instruction first.  */      output_asm_insn (template, operands);      /* Now recognize the insn which we put in its delay slot.	 We must do this after outputing the branch insn,	 since operands may just be a pointer to `recog_operand'.  */      insn_code_number = recog (pat, delay_insn);      if (insn_code_number == -1)	abort ();      for (i = 0; i < insn_n_operands[insn_code_number]; i++)	{	  if (GET_CODE (recog_operand[i]) == SUBREG)	    recog_operand[i] = alter_subreg (recog_operand[i]);	}      /* Now get the template for what this insn would	 have been, without the branch.  Its operands are	 exactly the same as they would be, so we don't	 need to do an insn_extract.  */      template = insn_template[insn_code_number];      if (template == 0)	template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);      output_asm_insn (template, recog_operand);    }  CC_STATUS_INIT;  return "";}/* Output a newly constructed insn DELAY_INSN.  */char *output_delay_insn (delay_insn)     rtx delay_insn;{  char *template;  extern rtx recog_operand[];  extern char call_used_regs[];  extern char *insn_template[];  extern int insn_n_operands[];  extern char *(*insn_outfun[])();  extern rtx alter_subreg();  int insn_code_number;  extern int insn_n_operands[];  int i;  /* Now recognize the insn which we put in its delay slot.     We must do this after outputing the branch insn,     since operands may just be a pointer to `recog_operand'.  */  insn_code_number = recog_memoized (delay_insn);  if (insn_code_number == -1)    abort ();  /* Extract the operands of this delay insn.  */  INSN_CODE (delay_insn) = insn_code_number;  insn_extract (delay_insn);  /* It is possible that this insn has not been properly scaned by final     yet.  If this insn's operands don't appear in the peephole's     actual operands, then they won't be fixed up by final, so we     make sure they get fixed up here.  -- This is a kludge.  */  for (i = 0; i < insn_n_operands[insn_code_number]; i++)    {      if (GET_CODE (recog_operand[i]) == SUBREG)	recog_operand[i] = alter_subreg (recog_operand[i]);    }#ifdef REGISTER_CONSTRAINTS  if (! constrain_operands (insn_code_number))    abort ();#endif  cc_prev_status = cc_status;  /* Update `cc_status' for this instruction.     The instruction's output routine may change it further.     If the output routine for a jump insn needs to depend     on the cc status, it should look at cc_prev_status.  */  NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);  /* Now get the template for what this insn would     have been, without the branch.  */  template = insn_template[insn_code_number];  if (template == 0)    template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);  output_asm_insn (template, recog_operand);  return "";}

⌨️ 快捷键说明

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