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

📄 ia64.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	{	  start_sequence ();	  if (! CONST_OK_FOR_I (disp))	    {	      rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());	      emit_move_insn (tmp, disp_rtx);	      disp_rtx = tmp;	    }	  emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],				 spill_fill_data.init_reg[iter],				 disp_rtx));	  seq = gen_sequence ();	  end_sequence ();	}      /* Careful for being the first insn in a sequence.  */      if (spill_fill_data.init_after)	insn = emit_insn_after (seq, spill_fill_data.init_after);      else	{	  rtx first = get_insns ();	  if (first)	    insn = emit_insn_before (seq, first);	  else	    insn = emit_insn (seq);	}      spill_fill_data.init_after = insn;      /* If DISP is 0, we may or may not have a further adjustment	 afterward.  If we do, then the load/store insn may be modified	 to be a post-modify.  If we don't, then this copy may be	 eliminated by copyprop_hardreg_forward, which makes this	 insn garbage, which runs afoul of the sanity check in	 propagate_one_insn.  So mark this insn as legal to delete.  */      if (disp == 0)	REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,					     REG_NOTES (insn));    }  mem = gen_rtx_MEM (GET_MODE (reg), spill_fill_data.iter_reg[iter]);  /* ??? Not all of the spills are for varargs, but some of them are.     The rest of the spills belong in an alias set of their own.  But     it doesn't actually hurt to include them here.  */  set_mem_alias_set (mem, get_varargs_alias_set ());  spill_fill_data.prev_addr[iter] = &XEXP (mem, 0);  spill_fill_data.prev_off[iter] = cfa_off;  if (++iter >= spill_fill_data.n_iter)    iter = 0;  spill_fill_data.next_iter = iter;  return mem;}static voiddo_spill (move_fn, reg, cfa_off, frame_reg)     rtx (*move_fn) PARAMS ((rtx, rtx, rtx));     rtx reg, frame_reg;     HOST_WIDE_INT cfa_off;{  int iter = spill_fill_data.next_iter;  rtx mem, insn;  mem = spill_restore_mem (reg, cfa_off);  insn = emit_insn ((*move_fn) (mem, reg, GEN_INT (cfa_off)));  spill_fill_data.prev_insn[iter] = insn;  if (frame_reg)    {      rtx base;      HOST_WIDE_INT off;      RTX_FRAME_RELATED_P (insn) = 1;      /* Don't even pretend that the unwind code can intuit its way 	 through a pair of interleaved post_modify iterators.  Just	 provide the correct answer.  */      if (frame_pointer_needed)	{	  base = hard_frame_pointer_rtx;	  off = - cfa_off;	}      else	{	  base = stack_pointer_rtx;	  off = current_frame_info.total_size - cfa_off;	}      REG_NOTES (insn)	= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,		gen_rtx_SET (VOIDmode,			     gen_rtx_MEM (GET_MODE (reg),					  plus_constant (base, off)),			     frame_reg),		REG_NOTES (insn));    }}static voiddo_restore (move_fn, reg, cfa_off)     rtx (*move_fn) PARAMS ((rtx, rtx, rtx));     rtx reg;     HOST_WIDE_INT cfa_off;{  int iter = spill_fill_data.next_iter;  rtx insn;  insn = emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off),				GEN_INT (cfa_off)));  spill_fill_data.prev_insn[iter] = insn;}/* Wrapper functions that discards the CONST_INT spill offset.  These   exist so that we can give gr_spill/gr_fill the offset they need and   use a consistant function interface.  */static rtxgen_movdi_x (dest, src, offset)     rtx dest, src;     rtx offset ATTRIBUTE_UNUSED;{  return gen_movdi (dest, src);}static rtxgen_fr_spill_x (dest, src, offset)     rtx dest, src;     rtx offset ATTRIBUTE_UNUSED;{  return gen_fr_spill (dest, src);}static rtxgen_fr_restore_x (dest, src, offset)     rtx dest, src;     rtx offset ATTRIBUTE_UNUSED;{  return gen_fr_restore (dest, src);}/* Called after register allocation to add any instructions needed for the   prologue.  Using a prologue insn is favored compared to putting all of the   instructions in output_function_prologue(), since it allows the scheduler   to intermix instructions with the saves of the caller saved registers.  In   some cases, it might be necessary to emit a barrier instruction as the last   insn to prevent such scheduling.   Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1   so that the debug info generation code can handle them properly.   The register save area is layed out like so:   cfa+16	[ varargs spill area ]	[ fr register spill area ]	[ br register spill area ]	[ ar register spill area ]	[ pr register spill area ]	[ gr register spill area ] *//* ??? Get inefficient code when the frame size is larger than can fit in an   adds instruction.  */voidia64_expand_prologue (){  rtx insn, ar_pfs_save_reg, ar_unat_save_reg;  int i, epilogue_p, regno, alt_regno, cfa_off, n_varargs;  rtx reg, alt_reg;  ia64_compute_frame_size (get_frame_size ());  last_scratch_gr_reg = 15;  /* If there is no epilogue, then we don't need some prologue insns.     We need to avoid emitting the dead prologue insns, because flow     will complain about them.  */  if (optimize)    {      edge e;      for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)	if ((e->flags & EDGE_FAKE) == 0	    && (e->flags & EDGE_FALLTHRU) != 0)	  break;      epilogue_p = (e != NULL);    }  else    epilogue_p = 1;  /* Set the local, input, and output register names.  We need to do this     for GNU libc, which creates crti.S/crtn.S by splitting initfini.c in     half.  If we use in/loc/out register names, then we get assembler errors     in crtn.S because there is no alloc insn or regstk directive in there.  */  if (! TARGET_REG_NAMES)    {      int inputs = current_frame_info.n_input_regs;      int locals = current_frame_info.n_local_regs;      int outputs = current_frame_info.n_output_regs;      for (i = 0; i < inputs; i++)	reg_names[IN_REG (i)] = ia64_reg_numbers[i];      for (i = 0; i < locals; i++)	reg_names[LOC_REG (i)] = ia64_reg_numbers[inputs + i];      for (i = 0; i < outputs; i++)	reg_names[OUT_REG (i)] = ia64_reg_numbers[inputs + locals + i];    }  /* Set the frame pointer register name.  The regnum is logically loc79,     but of course we'll not have allocated that many locals.  Rather than     worrying about renumbering the existing rtxs, we adjust the name.  */  /* ??? This code means that we can never use one local register when     there is a frame pointer.  loc79 gets wasted in this case, as it is     renamed to a register that will never be used.  See also the try_locals     code in find_gr_spill.  */  if (current_frame_info.reg_fp)    {      const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];      reg_names[HARD_FRAME_POINTER_REGNUM]	= reg_names[current_frame_info.reg_fp];      reg_names[current_frame_info.reg_fp] = tmp;    }  /* Fix up the return address placeholder.  */  /* ??? We can fail if __builtin_return_address is used, and we didn't     allocate a register in which to save b0.  I can't think of a way to     eliminate RETURN_ADDRESS_POINTER_REGNUM to a local register and     then be sure that I got the right one.  Further, reload doesn't seem     to care if an eliminable register isn't used, and "eliminates" it     anyway.  */  if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM]      && current_frame_info.reg_save_b0 != 0)    XINT (return_address_pointer_rtx, 0) = current_frame_info.reg_save_b0;  /* We don't need an alloc instruction if we've used no outputs or locals.  */  if (current_frame_info.n_local_regs == 0      && current_frame_info.n_output_regs == 0      && current_frame_info.n_input_regs <= current_function_args_info.int_regs)    {      /* If there is no alloc, but there are input registers used, then we	 need a .regstk directive.  */      current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);      ar_pfs_save_reg = NULL_RTX;    }  else    {      current_frame_info.need_regstk = 0;      if (current_frame_info.reg_save_ar_pfs)	regno = current_frame_info.reg_save_ar_pfs;      else	regno = next_scratch_gr_reg ();      ar_pfs_save_reg = gen_rtx_REG (DImode, regno);      insn = emit_insn (gen_alloc (ar_pfs_save_reg, 				   GEN_INT (current_frame_info.n_input_regs),				   GEN_INT (current_frame_info.n_local_regs),				   GEN_INT (current_frame_info.n_output_regs),				   GEN_INT (current_frame_info.n_rotate_regs)));      RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_pfs != 0);    }  /* Set up frame pointer, stack pointer, and spill iterators.  */  n_varargs = cfun->machine->n_varargs;  setup_spill_pointers (current_frame_info.n_spilled + n_varargs,			stack_pointer_rtx, 0);  if (frame_pointer_needed)    {      insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);      RTX_FRAME_RELATED_P (insn) = 1;    }  if (current_frame_info.total_size != 0)    {      rtx frame_size_rtx = GEN_INT (- current_frame_info.total_size);      rtx offset;      if (CONST_OK_FOR_I (- current_frame_info.total_size))	offset = frame_size_rtx;      else	{	  regno = next_scratch_gr_reg (); 	  offset = gen_rtx_REG (DImode, regno);	  emit_move_insn (offset, frame_size_rtx);	}      insn = emit_insn (gen_adddi3 (stack_pointer_rtx,				    stack_pointer_rtx, offset));      if (! frame_pointer_needed)	{	  RTX_FRAME_RELATED_P (insn) = 1;	  if (GET_CODE (offset) != CONST_INT)	    {	      REG_NOTES (insn)		= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,			gen_rtx_SET (VOIDmode,				     stack_pointer_rtx,				     gen_rtx_PLUS (DImode,						   stack_pointer_rtx,						   frame_size_rtx)),			REG_NOTES (insn));	    }	}      /* ??? At this point we must generate a magic insn that appears to	 modify the stack pointer, the frame pointer, and all spill	 iterators.  This would allow the most scheduling freedom.  For	 now, just hard stop.  */      emit_insn (gen_blockage ());    }  /* Must copy out ar.unat before doing any integer spills.  */  if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))    {      if (current_frame_info.reg_save_ar_unat)	ar_unat_save_reg	  = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);      else	{	  alt_regno = next_scratch_gr_reg ();	  ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);	  current_frame_info.gr_used_mask |= 1 << alt_regno;	}      reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);      insn = emit_move_insn (ar_unat_save_reg, reg);      RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_unat != 0);      /* Even if we're not going to generate an epilogue, we still	 need to save the register so that EH works.  */      if (! epilogue_p && current_frame_info.reg_save_ar_unat)	emit_insn (gen_prologue_use (ar_unat_save_reg));    }  else    ar_unat_save_reg = NULL_RTX;  /* Spill all varargs registers.  Do this before spilling any GR registers,     since we want the UNAT bits for the GR registers to override the UNAT     bits from varargs, which we don't care about.  */  cfa_off = -16;  for (regno = GR_ARG_FIRST + 7; n_varargs > 0; --n_varargs, --regno)    {      reg = gen_rtx_REG (DImode, regno);      do_spill (gen_gr_spill, reg, cfa_off += 8, NULL_RTX);    }  /* Locate the bottom of the register save area.  */  cfa_off = (current_frame_info.spill_cfa_off	     + current_frame_info.spill_size	     + current_frame_info.extra_spill_size);  /* Save the predicate register block either in a register or in memory.  */  if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))    {      reg = gen_rtx_REG (DImode, PR_REG (0));      if (current_frame_info.reg_save_pr != 0)	{	  alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);	  insn = emit_move_insn (alt_reg, reg);	  /* ??? Denote pr spill/fill by a DImode move that modifies all	     64 hard registers.  */	  RTX_FRAME_RELATED_P (insn) = 1;	  REG_NOTES (insn)	    = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,			gen_rtx_SET (VOIDmode, alt_reg, reg),			REG_NOTES (insn));	  /* Even if we're not going to generate an epilogue, we still	     need to save the register so that EH works.  */	  if (! epilogue_p)	    emit_insn (gen_prologue_use (alt_reg));	}      else	{	  alt_regno = next_scratch_gr_reg ();	  alt_reg = gen_rtx_REG (DImode, alt_regno);	  insn = emit_move_insn (alt_reg, reg);	  do_spill (gen_movdi_x, alt_reg, cfa_off, reg);	  cfa_off -= 8;	}    }  /* Handle AR regs in numerical order.  All of them get special handling.  */  if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)      && current_frame_info.reg_save_ar_unat == 0)    {      reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);      do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg);      cfa_off -= 8;    }  /* The alloc insn already copied ar.pfs into a general register.  The     only thing we have to do now is copy that register to a stack slot     if we'd not allocated a local register for the job.  */  if (current_frame_info.reg_save_ar_pfs == 0      && ! current_function_is_leaf)    {      reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);      do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);      cfa_off -= 8;    }  if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))    {      reg = gen_rtx_REG (DImode, AR_LC_REGNUM);      if (current_frame_info.reg_save_ar_lc != 0)	{	  alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);	  insn = emit_move_insn (alt_reg, reg);	  RTX_FRAME_RELATED_P (insn) = 1;	  /* Even if we're not going to generate an epilogue, we still	     need to save the register so that EH works.  */	  if (! epilogue_p)	    emit_insn (gen_prologue_use (alt_reg));	}      else	{	  alt_regno = next_scratch_gr_reg ();	  alt_reg = gen_rtx_REG (DImode, alt_regno);	  emit_move_insn (alt_reg, reg);	  do_spill (gen_movdi_x, alt_reg, cfa_off, reg);	  cfa_off -= 8;	}    }  /* We should now be at the base of the gr/br/fr spill area.  */  if (cfa_off != (current_frame_info.spill_cfa_off		  + current_frame_info.spill_size))    abort ();  /* Spill all general registers.  */  for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)    if (TEST_HARD_REG_BIT (curre

⌨️ 快捷键说明

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