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

📄 sparc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  rtx cc_reg = gen_rtx (REG, mode, 0);  emit_insn (gen_rtx (SET, VOIDmode, cc_reg,		      gen_rtx (COMPARE, mode, x, y)));  return cc_reg;}/* Return nonzero if a return peephole merging return with   setting of output register is ok.  */intleaf_return_peephole_ok (){  return (actual_fsize == 0);}/* Return nonzero if TRIAL can go into the function epilogue's   delay slot.  SLOT is the slot we are trying to fill.  */inteligible_for_epilogue_delay (trial, slot)     rtx trial;     int slot;{  static char *this_function_name;  rtx pat, src;  if (slot >= 1)    return 0;  if (GET_CODE (trial) != INSN      || GET_CODE (PATTERN (trial)) != SET)    return 0;  if (get_attr_length (trial) != 1)    return 0;  /* In the case of a true leaf function, anything can go into the delay slot.     A delay slot only exists however if the frame size is zero, otherwise     we will put an insn to adjust the stack after the return.  */  if (leaf_function)    {      if (leaf_return_peephole_ok ())	return (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);      return 0;    }  /* Otherwise, only operations which can be done in tandem with     a `restore' insn can go into the delay slot.  */  pat = PATTERN (trial);  if (GET_CODE (SET_DEST (pat)) != REG      || REGNO (SET_DEST (pat)) == 0      || REGNO (SET_DEST (pat)) >= 32      || REGNO (SET_DEST (pat)) < 24)    return 0;  src = SET_SRC (pat);  if (arith_operand (src, GET_MODE (src)))    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);  if (arith_double_operand (src, GET_MODE (src)))    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);  if (GET_CODE (src) == PLUS)    {      if (register_operand (XEXP (src, 0), SImode)	  && arith_operand (XEXP (src, 1), SImode))	return 1;      if (register_operand (XEXP (src, 1), SImode)	  && arith_operand (XEXP (src, 0), SImode))	return 1;      if (register_operand (XEXP (src, 0), DImode)	  && arith_double_operand (XEXP (src, 1), DImode))	return 1;      if (register_operand (XEXP (src, 1), DImode)	  && arith_double_operand (XEXP (src, 0), DImode))	return 1;    }  if (GET_CODE (src) == MINUS      && register_operand (XEXP (src, 0), SImode)      && small_int (XEXP (src, 1), VOIDmode))    return 1;  if (GET_CODE (src) == MINUS      && register_operand (XEXP (src, 0), DImode)      && !register_operand (XEXP (src, 1), DImode)      && arith_double_operand (XEXP (src, 1), DImode))    return 1;  return 0;}intshort_branch (uid1, uid2)     int uid1, uid2;{  unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];  if (delta + 1024 < 2048)    return 1;  /* warning ("long branch, distance %d", delta); */  return 0;}/* Return non-zero if REG is not used after INSN.   We assume REG is a reload reg, and therefore does   not live past labels or calls or jumps.  */intreg_unused_after (reg, insn)     rtx reg;     rtx insn;{  enum rtx_code code, prev_code = UNKNOWN;  while (insn = NEXT_INSN (insn))    {      if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])	return 1;      code = GET_CODE (insn);      if (GET_CODE (insn) == CODE_LABEL)	return 1;      if (GET_RTX_CLASS (code) == 'i')	{	  rtx set = single_set (insn);	  int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));	  if (set && in_src)	    return 0;	  if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))	    return 1;	  if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))	    return 0;	}      prev_code = code;    }  return 1;}/* Legitimize PIC addresses.  If the address is already position-independent,   we return ORIG.  Newly generated position-independent addresses go into a   reg.  This is REG if non zero, otherwise we allocate register(s) as   necessary.  If this is called during reload, and we need a second temp   register, then we use SCRATCH, which is provided via the   SECONDARY_INPUT_RELOAD_CLASS mechanism.  */rtxlegitimize_pic_address (orig, mode, reg, scratch)     rtx orig;     enum machine_mode mode;     rtx reg, scratch;{  if (GET_CODE (orig) == SYMBOL_REF)    {      rtx pic_ref, address;      rtx insn;      if (reg == 0)	{	  if (reload_in_progress || reload_completed)	    abort ();	  else	    reg = gen_reg_rtx (Pmode);	}      if (flag_pic == 2)	{	  /* If not during reload, allocate another temp reg here for loading	     in the address, so that these instructions can be optimized	     properly.  */	  rtx temp_reg = ((reload_in_progress || reload_completed)			  ? reg : gen_reg_rtx (Pmode));	  /* Must put the SYMBOL_REF inside an UNSPEC here so that cse	     won't get confused into thinking that these two instructions	     are loading in the true address of the symbol.  If in the	     future a PIC rtx exists, that should be used instead.  */	  emit_insn (gen_rtx (SET, VOIDmode, temp_reg,			      gen_rtx (HIGH, Pmode,				       gen_rtx (UNSPEC, Pmode,						gen_rtvec (1, orig),						0))));	  emit_insn (gen_rtx (SET, VOIDmode, temp_reg,			      gen_rtx (LO_SUM, Pmode, temp_reg,				       gen_rtx (UNSPEC, Pmode,						gen_rtvec (1, orig),						0))));	  address = temp_reg;	}      else	address = orig;      pic_ref = gen_rtx (MEM, Pmode,			 gen_rtx (PLUS, Pmode,				  pic_offset_table_rtx, address));      current_function_uses_pic_offset_table = 1;      RTX_UNCHANGING_P (pic_ref) = 1;      insn = emit_move_insn (reg, pic_ref);      /* Put a REG_EQUAL note on this insn, so that it can be optimized	 by loop.  */      REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,				  REG_NOTES (insn));      return reg;    }  else if (GET_CODE (orig) == CONST)    {      rtx base, offset;      if (GET_CODE (XEXP (orig, 0)) == PLUS	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)	return orig;      if (reg == 0)	{	  if (reload_in_progress || reload_completed)	    abort ();	  else	    reg = gen_reg_rtx (Pmode);	}      if (GET_CODE (XEXP (orig, 0)) == PLUS)	{	  base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,					 reg, 0);	  offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,					 base == reg ? 0 : reg, 0);	}      else	abort ();      if (GET_CODE (offset) == CONST_INT)	{	  if (SMALL_INT (offset))	    return plus_constant_for_output (base, INTVAL (offset));	  else if (! reload_in_progress && ! reload_completed)	    offset = force_reg (Pmode, offset);	  /* We can't create any new registers during reload, so use the	     SCRATCH reg provided by the reload_insi pattern.  */	  else if (scratch)	    {	      emit_move_insn (scratch, offset);	      offset = scratch;	    }	  else	    /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS	       macro needs to be adjusted so that a scratch reg is provided	       for this address.  */	    abort ();	}      return gen_rtx (PLUS, Pmode, base, offset);    }  else if (GET_CODE (orig) == LABEL_REF)    current_function_uses_pic_offset_table = 1;  return orig;}/* Set up PIC-specific rtl.  This should not cause any insns   to be emitted.  */voidinitialize_pic (){}/* Emit special PIC prologues and epilogues.  */voidfinalize_pic (){  /* The table we use to reference PIC data.  */  rtx global_offset_table;  /* Labels to get the PC in the prologue of this function.  */  rtx l1, l2;  rtx seq;  int orig_flag_pic = flag_pic;  if (current_function_uses_pic_offset_table == 0)    return;  if (! flag_pic)    abort ();  flag_pic = 0;  l1 = gen_label_rtx ();  l2 = gen_label_rtx ();  start_sequence ();  emit_label (l1);  /* Note that we pun calls and jumps here!  */  emit_jump_insn (gen_rtx (PARALLEL, VOIDmode,                         gen_rtvec (2,                                    gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)),                                    gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2)))));  emit_label (l2);  /* Initialize every time through, since we can't easily     know this to be permanent.  */  global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "_GLOBAL_OFFSET_TABLE_");  pic_pc_rtx = gen_rtx (CONST, Pmode,			gen_rtx (MINUS, Pmode,				 global_offset_table,				 gen_rtx (CONST, Pmode,					  gen_rtx (MINUS, Pmode,						   gen_rtx (LABEL_REF, VOIDmode, l1),						   pc_rtx))));  emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,		      gen_rtx (HIGH, Pmode, pic_pc_rtx)));  emit_insn (gen_rtx (SET, VOIDmode,		      pic_offset_table_rtx,		      gen_rtx (LO_SUM, Pmode,			       pic_offset_table_rtx, pic_pc_rtx)));  emit_insn (gen_rtx (SET, VOIDmode,		      pic_offset_table_rtx,		      gen_rtx (PLUS, Pmode,			       pic_offset_table_rtx, gen_rtx (REG, Pmode, 15))));  /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */  LABEL_PRESERVE_P (l1) = 1;  LABEL_PRESERVE_P (l2) = 1;  flag_pic = orig_flag_pic;  seq = gen_sequence ();  end_sequence ();  emit_insn_after (seq, get_insns ());  /* Need to emit this whether or not we obey regdecls,     since setjmp/longjmp can cause life info to screw up.  */  emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));}/* For the SPARC, REG and REG+CONST is cost 0, REG+REG is cost 1,   and addresses involving symbolic constants are cost 2.   We make REG+REG slightly more expensive because it might keep   a register live for longer than we might like.   PIC addresses are very expensive.   It is no coincidence that this has the same structure   as GO_IF_LEGITIMATE_ADDRESS.  */intsparc_address_cost (X)     rtx X;{#if 0  /* Handled before calling here.  */  if (GET_CODE (X) == REG)    { return 1; }#endif  if (GET_CODE (X) == PLUS)    {      if (GET_CODE (XEXP (X, 0)) == REG	  && GET_CODE (XEXP (X, 1)) == REG)	return 2;      return 1;    }  else if (GET_CODE (X) == LO_SUM)    return 1;  else if (GET_CODE (X) == HIGH)    return 2;  return 4;}/* Emit insns to move operands[1] into operands[0].   Return 1 if we have written out everything that needs to be done to   do the move.  Otherwise, return 0 and the caller will emit the move   normally.   SCRATCH_REG if non zero can be used as a scratch register for the move   operation.  It is provided by a SECONDARY_RELOAD_* macro if needed.  */intemit_move_sequence (operands, mode, scratch_reg)     rtx *operands;     enum machine_mode mode;     rtx scratch_reg;{  register rtx operand0 = operands[0];  register rtx operand1 = operands[1];  /* Handle most common case first: storing into a register.  */  if (register_operand (operand0, mode))    {      if (register_operand (operand1, mode)	  || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))	  || (GET_CODE (operand1) == CONST_DOUBLE	      && arith_double_operand (operand1, DImode))	  || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) != DImode)	  /* Only `general_operands' can come here, so MEM is ok.  */	  || GET_CODE (operand1) == MEM)	{	  /* Run this case quickly.  */	  emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));	  return 1;	}    }  else if (GET_CODE (operand0) == MEM)    {      if (register_operand (operand1, mode) || operand1 == const0_rtx)	{	  /* Run this case quickly.  */	  emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));	  return 1;	}      if (! reload_in_progress)	{	  operands[0] = validize_mem (operand0);	  operands[1] = operand1 = force_reg (mode, operand1);	}    }  /* Simplify the source if we need to.  Must handle DImode HIGH operators     here because such a move needs a clobber added.  */  if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))      || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode))    {      if (flag_pic && symbolic_operand (operand1, mode))	{	  rtx temp_reg = reload_in_progress ? operand0 : 0;	  operands[1] = legitimize_pic_address (operand1, mode, temp_reg,						scratch_reg);	}      else if (GET_CODE (operand1) == CONST_INT	       ? (! SMALL_INT (operand1)		  && (INTVAL (operand1) & 0x3ff) != 0)	       : (GET_CODE (operand1) == CONST_DOUBLE		  ? ! arith_double_operand (operand1, DImode)		  : 1))	{	  /* For DImode values, temp must be operand0 because of the way	     HI and LO_SUM work.  The LO_SUM operator only copies half of	     the LSW from the dest of the HI operator.  If the LO_SUM dest is	     not the same as the HI dest, then the MSW of the LO_SUM dest will	     never be set.	     ??? The real problem here is that the ...(HI:DImode pattern emits	     multiple instructions, and the ...(LO_SUM:DImode pattern emits	     one instruction.  This fails, because the compiler assumes that	     LO_SUM copies all bits of the first operand to its dest.  Better	     would be to have the HI pattern emit one instruction and the	     LO_SUM pattern multiple instructions.  Even better would be	     to use four rtl insns.  */	  rtx temp = ((reload_in_progress || mode == DImode)		      ? operand0 : gen_reg_rtx (mode));	  emit_insn (gen_rtx (SET, VOIDmode, temp,			      gen_rtx (HIGH, mode, operand1)));	  operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);	}    }  if (GET_CODE (operand1) == LABEL_REF && flag_pic)    {      /* The procedure for doing this involves using a call instruction to	 get the pc into o7.  We need to indicate this explicitly because	 the tablejump pattern assumes that it can use this value also.  */      emit_insn (gen_rtx (PARALLEL, VOIDmode,			  gen_rtvec (2,				     gen_rtx (SET, VOIDmode, operand0,					      operand1),				     gen_rtx (SET, VOIDmode,					      gen_rtx (REG, mode, 15),

⌨️ 快捷键说明

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