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

📄 stormy16.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
	direction = -1;      else if (refers_to_regno_p (regno + num_words - 1, regno + num_words,				  mem_operand, 0))	direction = 1;      else	/* This means something like	   (set (reg:DI r0) (mem:DI (reg:HI r1)))	   which we'd need to support by doing the set of the second word	   last.  */	gcc_unreachable ();    }  end = direction < 0 ? -1 : num_words;  for (i = direction < 0 ? num_words - 1 : 0; i != end; i += direction)    {      rtx w_src, w_dest, insn;      if (src_modifies)	w_src = gen_rtx_MEM (word_mode, mem_operand);      else	w_src = simplify_gen_subreg (word_mode, src, mode, i * UNITS_PER_WORD);      if (src_volatile)	MEM_VOLATILE_P (w_src) = 1;      if (dest_modifies)	w_dest = gen_rtx_MEM (word_mode, mem_operand);      else	w_dest = simplify_gen_subreg (word_mode, dest, mode, 				      i * UNITS_PER_WORD);      if (dest_volatile)	MEM_VOLATILE_P (w_dest) = 1;            /* The simplify_subreg calls must always be able to simplify.  */      gcc_assert (GET_CODE (w_src) != SUBREG		  && GET_CODE (w_dest) != SUBREG);            insn = emit_insn (gen_rtx_SET (VOIDmode, w_dest, w_src));      if (auto_inc_reg_rtx)        REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,                                            auto_inc_reg_rtx,					    REG_NOTES (insn));    }}/* Expander for the 'move' patterns.  Emit insns to copy a value of   mode MODE from SRC to DEST.  */void xstormy16_expand_move (enum machine_mode mode, rtx dest, rtx src){  if ((GET_CODE (dest) == MEM) && (GET_CODE (XEXP (dest, 0)) == PRE_MODIFY))    {      rtx pmv      = XEXP (dest, 0);      rtx dest_reg = XEXP (pmv, 0);      rtx dest_mod = XEXP (pmv, 1);      rtx set      = gen_rtx_SET (Pmode, dest_reg, dest_mod);      rtx clobber  = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, 16));          dest = gen_rtx_MEM (mode, dest_reg);      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));    }  else if ((GET_CODE (src) == MEM) && (GET_CODE (XEXP (src, 0)) == PRE_MODIFY))    {      rtx pmv     = XEXP (src, 0);      rtx src_reg = XEXP (pmv, 0);      rtx src_mod = XEXP (pmv, 1);      rtx set     = gen_rtx_SET (Pmode, src_reg, src_mod);      rtx clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, 16));          src = gen_rtx_MEM (mode, src_reg);      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));    }     /* There are only limited immediate-to-memory move instructions.  */  if (! reload_in_progress      && ! reload_completed      && GET_CODE (dest) == MEM      && (GET_CODE (XEXP (dest, 0)) != CONST_INT	  || ! xstormy16_legitimate_address_p (mode, XEXP (dest, 0), 0))      && ! xstormy16_below100_operand (dest, mode)      && GET_CODE (src) != REG      && GET_CODE (src) != SUBREG)    src = copy_to_mode_reg (mode, src);  /* Don't emit something we would immediately split.  */  if (reload_completed      && mode != HImode && mode != QImode)    {      xstormy16_split_move (mode, dest, src);      return;    }    emit_insn (gen_rtx_SET (VOIDmode, dest, src));}/* Stack Layout:   The stack is laid out as follows:SP->FP->	Local variables	Register save area (up to 4 words)	Argument register save area for stdarg (NUM_ARGUMENT_REGISTERS words)AP->	Return address (two words)	9th procedure parameter word	10th procedure parameter word	...	last procedure parameter word  The frame pointer location is tuned to make it most likely that all  parameters and local variables can be accessed using a load-indexed  instruction.  *//* A structure to describe the layout.  */struct xstormy16_stack_layout{  /* Size of the topmost three items on the stack.  */  int locals_size;  int register_save_size;  int stdarg_save_size;  /* Sum of the above items.  */  int frame_size;  /* Various offsets.  */  int first_local_minus_ap;  int sp_minus_fp;  int fp_minus_ap;};/* Does REGNO need to be saved?  */#define REG_NEEDS_SAVE(REGNUM, IFUN)					\  ((regs_ever_live[REGNUM] && ! call_used_regs[REGNUM])			\   || (IFUN && ! fixed_regs[REGNUM] && call_used_regs[REGNUM]		\       && (REGNO_REG_CLASS (REGNUM) != CARRY_REGS)			\       && (regs_ever_live[REGNUM] || ! current_function_is_leaf)))/* Compute the stack layout.  */struct xstormy16_stack_layout xstormy16_compute_stack_layout (void){  struct xstormy16_stack_layout layout;  int regno;  const int ifun = xstormy16_interrupt_function_p ();  layout.locals_size = get_frame_size ();    layout.register_save_size = 0;  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)    if (REG_NEEDS_SAVE (regno, ifun))      layout.register_save_size += UNITS_PER_WORD;    if (current_function_stdarg)    layout.stdarg_save_size = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD;  else    layout.stdarg_save_size = 0;    layout.frame_size = (layout.locals_size 		       + layout.register_save_size 		       + layout.stdarg_save_size);    if (current_function_args_size <= 2048 && current_function_args_size != -1)    {      if (layout.frame_size + INCOMING_FRAME_SP_OFFSET 	  + current_function_args_size <= 2048)	layout.fp_minus_ap = layout.frame_size + INCOMING_FRAME_SP_OFFSET;      else	layout.fp_minus_ap = 2048 - current_function_args_size;    }  else    layout.fp_minus_ap = (layout.stdarg_save_size 			  + layout.register_save_size			  + INCOMING_FRAME_SP_OFFSET);  layout.sp_minus_fp = (layout.frame_size + INCOMING_FRAME_SP_OFFSET 			- layout.fp_minus_ap);  layout.first_local_minus_ap = layout.sp_minus_fp - layout.locals_size;  return layout;}/* Determine how all the special registers get eliminated.  */intxstormy16_initial_elimination_offset (int from, int to){  struct xstormy16_stack_layout layout;  int result;    layout = xstormy16_compute_stack_layout ();  if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)    result = layout.sp_minus_fp - layout.locals_size;  else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)    result = -layout.locals_size;  else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)    result = -layout.fp_minus_ap;  else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)    result = -(layout.sp_minus_fp + layout.fp_minus_ap);  else    gcc_unreachable ();  return result;}static rtxemit_addhi3_postreload (rtx dest, rtx src0, rtx src1){  rtx set, clobber, insn;    set = gen_rtx_SET (VOIDmode, dest, gen_rtx_PLUS (HImode, src0, src1));  clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, 16));  insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));  return insn;}/* 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 the TARGET_ASM_FUNCTION_PROLOGUE macro,   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.  */voidxstormy16_expand_prologue (void){  struct xstormy16_stack_layout layout;  int regno;  rtx insn;  rtx mem_push_rtx;  const int ifun = xstormy16_interrupt_function_p ();    mem_push_rtx = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);  mem_push_rtx = gen_rtx_MEM (HImode, mem_push_rtx);      layout = xstormy16_compute_stack_layout ();  if (layout.locals_size >= 32768)    error ("local variable memory requirements exceed capacity");  /* Save the argument registers if necessary.  */  if (layout.stdarg_save_size)    for (regno = FIRST_ARGUMENT_REGISTER; 	 regno < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS;	 regno++)      {	rtx dwarf;	rtx reg = gen_rtx_REG (HImode, regno);	insn = emit_move_insn (mem_push_rtx, reg);	RTX_FRAME_RELATED_P (insn) = 1;	dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));		XVECEXP (dwarf, 0, 0) = gen_rtx_SET (VOIDmode,					     gen_rtx_MEM (Pmode, stack_pointer_rtx),					     reg);	XVECEXP (dwarf, 0, 1) = gen_rtx_SET (Pmode, stack_pointer_rtx,					     plus_constant (stack_pointer_rtx,							    GET_MODE_SIZE (Pmode)));	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,					      dwarf,					      REG_NOTES (insn));	RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 0)) = 1;	RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 1)) = 1;      }    /* Push each of the registers to save.  */  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)    if (REG_NEEDS_SAVE (regno, ifun))      {	rtx dwarf;	rtx reg = gen_rtx_REG (HImode, regno);	insn = emit_move_insn (mem_push_rtx, reg);	RTX_FRAME_RELATED_P (insn) = 1;	dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));		XVECEXP (dwarf, 0, 0) = gen_rtx_SET (VOIDmode,					     gen_rtx_MEM (Pmode, stack_pointer_rtx),					     reg);	XVECEXP (dwarf, 0, 1) = gen_rtx_SET (Pmode, stack_pointer_rtx,					     plus_constant (stack_pointer_rtx,							    GET_MODE_SIZE (Pmode)));	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,					      dwarf,					      REG_NOTES (insn));	RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 0)) = 1;	RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 1)) = 1;      }  /* It's just possible that the SP here might be what we need for     the new FP...  */  if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size)    emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);  /* Allocate space for local variables.  */  if (layout.locals_size)    {      insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,				     GEN_INT (layout.locals_size));      RTX_FRAME_RELATED_P (insn) = 1;    }  /* Set up the frame pointer, if required.  */  if (frame_pointer_needed && layout.sp_minus_fp != layout.locals_size)    {      insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);      if (layout.sp_minus_fp)	emit_addhi3_postreload (hard_frame_pointer_rtx,				hard_frame_pointer_rtx,				GEN_INT (-layout.sp_minus_fp));    }}/* Do we need an epilogue at all?  */intdirect_return (void){  return (reload_completed 	  && xstormy16_compute_stack_layout ().frame_size == 0);}/* Called after register allocation to add any instructions needed for   the epilogue.  Using an epilogue insn is favored compared to putting   all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,   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.  */voidxstormy16_expand_epilogue (void){  struct xstormy16_stack_layout layout;  rtx mem_pop_rtx, insn;  int regno;  const int ifun = xstormy16_interrupt_function_p ();    mem_pop_rtx = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);  mem_pop_rtx = gen_rtx_MEM (HImode, mem_pop_rtx);    layout = xstormy16_compute_stack_layout ();  /* Pop the stack for the locals.  */  if (layout.locals_size)    {      if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size)	emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);      else        {	  insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,					 GEN_INT (- layout.locals_size));	  RTX_FRAME_RELATED_P (insn) = 1;	}    }  /* Restore any call-saved registers.  */  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)    if (REG_NEEDS_SAVE (regno, ifun))      {        rtx dwarf;	insn = emit_move_insn (gen_rtx_REG (HImode, regno), mem_pop_rtx);	RTX_FRAME_RELATED_P (insn) = 1;	dwarf = gen_rtx_SET (Pmode, stack_pointer_rtx,			     plus_constant (stack_pointer_rtx,					    -GET_MODE_SIZE (Pmode)));	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,					      dwarf,					      REG_NOTES (insn));      }    /* Pop the stack for the stdarg save area.  */  if (layout.stdarg_save_size)    {      insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,				     GEN_INT (- layout.stdarg_save_size));      RTX_FRAME_RELATED_P (insn) = 1;    }  /* Return.  */  if (ifun)    emit_jump_insn (gen_return_internal_interrupt ());  else    emit_jump_insn (gen_return_internal ());}intxstormy16_epilogue_uses (int regno){  if (reload_completed && call_used_regs[regno])    {      const int ifun = xstormy16_interrupt_function_p ();      return REG_NEEDS_SAVE (regno, ifun);    }  return 0;}voidxstormy16_function_profiler (void){  sorry ("function_profiler support");}/* Return an updated summarizer variable CUM to advance past an   argument in the argument list.  The values MODE, TYPE and NAMED   describe that argument.  Once this is done, the variable CUM is   suitable for analyzing the *following* argument with   `FUNCTION_ARG', etc.   This function need not do anything if the argument in question was   passed on the stack.  The compiler knows how to track the amount of   stack space used for arguments without any special help.  However,   it makes life easier for xstormy16_build_va_list if it does update   the word count.  */CUMULATIVE_ARGSxstormy16_function_arg_advance (CUMULATIVE_ARGS cum, enum machine_mode mode,				tree type, int named ATTRIBUTE_UNUSED){  /* If an argument would otherwise be passed partially in registers,     and partially on the stack, the whole of it is passed on the     stack.  */  if (cum < NUM_ARGUMENT_REGISTERS      && cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)    cum = NUM_ARGUMENT_REGISTERS;    cum += XSTORMY16_WORD_SIZE (type, mode);    return cum;}rtx

⌨️ 快捷键说明

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