v850.c

来自「linux下的gcc编译器」· C语言 代码 · 共 2,603 行 · 第 1/5 页

C
2,603
字号
	 registers that need to be saved.  To detect this we note that the	 helper functions always push at least register r29 (provided	 that the function is not an interrupt handler).  */	       if (TARGET_PROLOG_FUNCTION          && (i == 2 || ((i >= 20) && (i < 30))))	{	  if (i == 2)	    {	      size += 4;	      reg_saved |= 1L << i;	      i = 20;	    }	  /* Helper functions save all registers between the starting	     register and the last register, regardless of whether they	     are actually used by the function or not.  */	  for (; i <= 29; i++)	    {	      size += 4;	      reg_saved |= 1L << i;	    }	  if (regs_ever_live [LINK_POINTER_REGNUM])	    {	      size += 4;	      reg_saved |= 1L << LINK_POINTER_REGNUM;	    }	}      else	{	  for (; i <= 31; i++)	    if (regs_ever_live[i] && ((! call_used_regs[i])				      || i == LINK_POINTER_REGNUM))	      {		size += 4;		reg_saved |= 1L << i;	      }	}    }    if (p_reg_saved)    *p_reg_saved = reg_saved;  return size;}intcompute_frame_size (size, p_reg_saved)     int size;     long *p_reg_saved;{  return (size	  + compute_register_save_size (p_reg_saved)	  + current_function_outgoing_args_size);}voidexpand_prologue (){  unsigned int i;  int offset;  unsigned int size = get_frame_size ();  unsigned int actual_fsize;  unsigned int init_stack_alloc = 0;  rtx save_regs[32];  rtx save_all;  unsigned int num_save;  unsigned int default_stack;  int code;  int interrupt_handler = v850_interrupt_function_p (current_function_decl);  long reg_saved = 0;  actual_fsize = compute_frame_size (size, &reg_saved);  /* Save/setup global registers for interrupt functions right now.  */  if (interrupt_handler)    {      if (TARGET_V850E && ! TARGET_DISABLE_CALLT)	emit_insn (gen_callt_save_interrupt ());      else	emit_insn (gen_save_interrupt ());      actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;            if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)	actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;    }  /* Save arg registers to the stack if necessary.  */  else if (current_function_args_info.anonymous_args)    {      if (TARGET_PROLOG_FUNCTION)	{	  if (TARGET_V850E && ! TARGET_DISABLE_CALLT)	    emit_insn (gen_save_r6_r9_v850e ());	  else	    emit_insn (gen_save_r6_r9 ());	}      else	{	  offset = 0;	  for (i = 6; i < 10; i++)	    {	      emit_move_insn (gen_rtx_MEM (SImode,					   plus_constant (stack_pointer_rtx,							  offset)),			      gen_rtx_REG (SImode, i));	      offset += 4;	    }	}    }  /* Identify all of the saved registers.  */  num_save = 0;  default_stack = 0;  for (i = 1; i < 31; i++)    {      if (((1L << i) & reg_saved) != 0)	save_regs[num_save++] = gen_rtx_REG (Pmode, i);    }  /* If the return pointer is saved, the helper functions also allocate     16 bytes of stack for arguments to be saved in.  */  if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)    {      save_regs[num_save++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);      default_stack = 16;    }  /* See if we have an insn that allocates stack space and saves the particular     registers we want to.  */  save_all = NULL_RTX;  if (TARGET_PROLOG_FUNCTION && num_save > 0 && actual_fsize >= default_stack)    {      int alloc_stack = (4 * num_save) + default_stack;      int unalloc_stack = actual_fsize - alloc_stack;      int save_func_len = 4;      int save_normal_len;      if (unalloc_stack)	save_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;      /* see if we would have used ep to save the stack */      if (TARGET_EP && num_save > 3 && (unsigned)actual_fsize < 255)	save_normal_len = (3 * 2) + (2 * num_save);      else	save_normal_len = 4 * num_save;      save_normal_len += CONST_OK_FOR_J (actual_fsize) ? 2 : 4;      /* Don't bother checking if we don't actually save any space.	 This happens for instance if one register is saved and additional	 stack space is allocated.  */      if (save_func_len < save_normal_len)	{	  save_all = gen_rtx_PARALLEL	    (VOIDmode,	     rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));	  XVECEXP (save_all, 0, 0)	    = gen_rtx_SET (VOIDmode,			   stack_pointer_rtx,			   plus_constant (stack_pointer_rtx, -alloc_stack));	  if (TARGET_V850)	    {	      XVECEXP (save_all, 0, num_save+1)		= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));	    }	  offset = - default_stack;	  for (i = 0; i < num_save; i++)	    {	      XVECEXP (save_all, 0, i+1)		= gen_rtx_SET (VOIDmode,			       gen_rtx_MEM (Pmode,					    plus_constant (stack_pointer_rtx,							   offset)),			       save_regs[i]);	      offset -= 4;	    }	  code = recog (save_all, NULL_RTX, NULL);	  if (code >= 0)	    {	      rtx insn = emit_insn (save_all);	      INSN_CODE (insn) = code;	      actual_fsize -= alloc_stack;	      	      if (TARGET_DEBUG)		fprintf (stderr, "\Saved %d bytes via prologue function (%d vs. %d) for function %s\n",			 save_normal_len - save_func_len,			 save_normal_len, save_func_len,			 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));	    }	  else	    save_all = NULL_RTX;	}    }  /* If no prolog save function is available, store the registers the old     fashioned way (one by one). */  if (!save_all)    {      /* Special case interrupt functions that save all registers for a call.  */      if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)	{	  if (TARGET_V850E && ! TARGET_DISABLE_CALLT)	    emit_insn (gen_callt_save_all_interrupt ());	  else	    emit_insn (gen_save_all_interrupt ());	}      else	{	  /* If the stack is too big, allocate it in chunks so we can do the	     register saves.  We use the register save size so we use the ep	     register.  */	  if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))	    init_stack_alloc = compute_register_save_size (NULL);	  else	    init_stack_alloc = actual_fsize;	      	  /* Save registers at the beginning of the stack frame */	  offset = init_stack_alloc - 4;	  	  if (init_stack_alloc)	    emit_insn (gen_addsi3 (stack_pointer_rtx,				   stack_pointer_rtx,				   GEN_INT (-init_stack_alloc)));	  	  /* Save the return pointer first.  */	  if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM)	    {	      emit_move_insn (gen_rtx_MEM (SImode,					   plus_constant (stack_pointer_rtx,							  offset)),			      save_regs[--num_save]);	      offset -= 4;	    }	  	  for (i = 0; i < num_save; i++)	    {	      emit_move_insn (gen_rtx_MEM (SImode,					   plus_constant (stack_pointer_rtx,							  offset)),			      save_regs[i]);	      offset -= 4;	    }	}    }  /* Allocate the rest of the stack that was not allocated above (either it is     > 32K or we just called a function to save the registers and needed more     stack.  */  if (actual_fsize > init_stack_alloc)    {      int diff = actual_fsize - init_stack_alloc;      if (CONST_OK_FOR_K (diff))	emit_insn (gen_addsi3 (stack_pointer_rtx,			       stack_pointer_rtx,			       GEN_INT (-diff)));      else	{	  rtx reg = gen_rtx_REG (Pmode, 12);	  emit_move_insn (reg, GEN_INT (-diff));	  emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));	}    }  /* If we need a frame pointer, set it up now.  */  if (frame_pointer_needed)    emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);}voidexpand_epilogue (){  unsigned int i;  int offset;  unsigned int size = get_frame_size ();  long reg_saved = 0;  unsigned int actual_fsize = compute_frame_size (size, &reg_saved);  unsigned int init_stack_free = 0;  rtx restore_regs[32];  rtx restore_all;  unsigned int num_restore;  unsigned int default_stack;  int code;  int interrupt_handler = v850_interrupt_function_p (current_function_decl);  /* Eliminate the initial stack stored by interrupt functions.  */  if (interrupt_handler)    {      actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;      if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)	actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;    }  /* Cut off any dynamic stack created.  */  if (frame_pointer_needed)    emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);  /* Identify all of the saved registers.  */  num_restore = 0;  default_stack = 0;  for (i = 1; i < 31; i++)    {      if (((1L << i) & reg_saved) != 0)	restore_regs[num_restore++] = gen_rtx_REG (Pmode, i);    }  /* If the return pointer is saved, the helper functions also allocate     16 bytes of stack for arguments to be saved in.  */  if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)    {      restore_regs[num_restore++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);      default_stack = 16;    }  /* See if we have an insn that restores the particular registers we     want to.  */  restore_all = NULL_RTX;    if (TARGET_PROLOG_FUNCTION      && num_restore > 0      && actual_fsize >= default_stack      && !interrupt_handler)    {      int alloc_stack = (4 * num_restore) + default_stack;      int unalloc_stack = actual_fsize - alloc_stack;      int restore_func_len = 4;      int restore_normal_len;      if (unalloc_stack)	restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;      /* See if we would have used ep to restore the registers.  */      if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255)	restore_normal_len = (3 * 2) + (2 * num_restore);      else	restore_normal_len = 4 * num_restore;      restore_normal_len += (CONST_OK_FOR_J (actual_fsize) ? 2 : 4) + 2;      /* Don't bother checking if we don't actually save any space.  */      if (restore_func_len < restore_normal_len)	{	  restore_all = gen_rtx_PARALLEL (VOIDmode,					  rtvec_alloc (num_restore + 2));	  XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);	  XVECEXP (restore_all, 0, 1)	    = gen_rtx_SET (VOIDmode, stack_pointer_rtx,			    gen_rtx_PLUS (Pmode,					  stack_pointer_rtx,					  GEN_INT (alloc_stack)));	  offset = alloc_stack - 4;	  for (i = 0; i < num_restore; i++)	    {	      XVECEXP (restore_all, 0, i+2)		= gen_rtx_SET (VOIDmode,			       restore_regs[i],			       gen_rtx_MEM (Pmode,					    plus_constant (stack_pointer_rtx,							   offset)));	      offset -= 4;	    }	  code = recog (restore_all, NULL_RTX, NULL);	  	  if (code >= 0)	    {	      rtx insn;	      actual_fsize -= alloc_stack;	      if (actual_fsize)		{		  if (CONST_OK_FOR_K (actual_fsize))		    emit_insn (gen_addsi3 (stack_pointer_rtx,					   stack_pointer_rtx,					   GEN_INT (actual_fsize)));		  else		    {		      rtx reg = gen_rtx_REG (Pmode, 12);		      emit_move_insn (reg, GEN_INT (actual_fsize));		      emit_insn (gen_addsi3 (stack_pointer_rtx,					     stack_pointer_rtx,					     reg));		    }		}	      insn = emit_jump_insn (restore_all);	      INSN_CODE (insn) = code;	      if (TARGET_DEBUG)		fprintf (stderr, "\Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",			 restore_normal_len - restore_func_len,			 restore_normal_len, restore_func_len,			 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));	    }	  else	    restore_all = NULL_RTX;	}    }  /* If no epilog save function is available, restore the registers the     old fashioned way (one by one).  */  if (!restore_all)    {      /* If the stack is large, we need to cut it down in 2 pieces.  */      if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))	init_stack_free = 4 * num_restore;      else	init_stack_free = actual_fsize;      /* Deallocate the rest of the stack if it is > 32K.  */      if (actual_fsize > init_stack_free)	{	  int diff;	  diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free);	  if (CONST_OK_FOR_K (diff))	    emit_insn (gen_addsi3 (stack_pointer_rtx,				   stack_pointer_rtx,				   GEN_INT (diff)));	  else	    {	      rtx reg = gen_rtx_REG (Pmode, 12);	      emit_move_insn (reg, GEN_INT (diff));	      emit_insn (gen_addsi3 (stack_pointer_rtx,				     stack_pointer_rtx,				     reg));	    }	}      /* Special case interrupt functions that save all registers	 for a call.  */      if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)	{	  if (TARGET_V850E && ! TARGET_DISABLE_CALLT)	    emit_insn (gen_callt_restore_all_interrupt ());	  else	    emit_insn (gen_restore_all_interrupt ());	}      else	{	  /* Restore registers from the beginning of the stack frame.  */	  offset = init_stack_free - 4;	  /* Restore the return pointer first.  */	  if (num_restore > 0	      && REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM)	    {	      emit_move_insn (restore_regs[--num_restore],			      gen_rtx_MEM (SImode,					   plus_constant (stack_pointer_rtx,							  offset)));	      offset -= 4;	    }	  for (i = 0; i < num_restore; i++)	    {	      emit_move_insn (restore_regs[i],			      gen_rtx_MEM (SImode,					   plus_constant (stack_pointer_rtx,							  offset)));	      emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i]));	      offset -= 4;	    }	  /* Cut back the remainder of the stack.  */	  if (init_stack_free)	    emit_insn (gen_addsi3 (stack_pointer_rtx,				   stack_pointer_rtx,				   GEN_INT (init_stack_free)));	}      /* And return or use reti for interrupt handlers.  */      if (interrupt_handler)        {          if (TARGET_V850E && ! TARGET_DISABLE_CALLT)            emit_insn (gen_callt_return_interrupt ());          else            emit_jump_insn (gen_return_interrupt ());	 }      else if (actual_fsize)	emit_jump_insn (gen_return_internal ());      else	emit_jump_insn (gen_return ());    }  v850_interrupt_cache_p = FALSE;  v850_interrupt_p = FALSE;}/* Update the condition code from the insn.  */voidnotice_update_cc (body, insn)     rtx body;     rtx insn;{  switch (get_attr_cc (insn))    {    case CC_NONE:      /* Insn does not affect CC at all.  */      break;    case CC_NONE_0HIT:      /* Insn does not change CC, but the 0'th operand has been changed.  */      if (cc_status.value1 != 0	  && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))

⌨️ 快捷键说明

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