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

📄 v850.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	{	  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,					      gen_rtx (PLUS, Pmode,						       stack_pointer_rtx,						       GEN_INT (-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_PTR);	  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)	{	  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_PTR);	  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)	{	  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)));	      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)	emit_jump_insn (gen_restore_interrupt ());      else if (actual_fsize)	emit_jump_insn (gen_return_internal ());      else	emit_jump_insn (gen_return ());    }  current_function_anonymous_args = 0;  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_operand[0], cc_status.value1))	cc_status.value1 = 0;      break;    case CC_SET_ZN:      /* Insn sets the Z,N flags of CC to recog_operand[0].	 V,C is in an unusable state.  */      CC_STATUS_INIT;      cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;      cc_status.value1 = recog_operand[0];      break;    case CC_SET_ZNV:      /* Insn sets the Z,N,V flags of CC to recog_operand[0].	 C is in an unusable state.  */      CC_STATUS_INIT;      cc_status.flags |= CC_NO_CARRY;      cc_status.value1 = recog_operand[0];      break;    case CC_COMPARE:      /* The insn is a compare instruction.  */      CC_STATUS_INIT;      cc_status.value1 = SET_SRC (body);      break;    case CC_CLOBBER:      /* Insn doesn't leave CC in a usable state.  */      CC_STATUS_INIT;      break;    }}/* Retrieve the data area that has been chosen for the given decl.  */v850_data_areav850_get_data_area (decl)     tree decl;{  if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)    return DATA_AREA_SDA;    if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)    return DATA_AREA_TDA;    if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)    return DATA_AREA_ZDA;  return DATA_AREA_NORMAL;}/* Store the indicated data area in the decl's attributes.  */static voidv850_set_data_area (decl, data_area)     tree decl;     v850_data_area data_area;{  tree name;    switch (data_area)    {    case DATA_AREA_SDA: name = get_identifier ("sda"); break;    case DATA_AREA_TDA: name = get_identifier ("tda"); break;    case DATA_AREA_ZDA: name = get_identifier ("zda"); break;    default:      return;    }  DECL_MACHINE_ATTRIBUTES (decl) = tree_cons    (name, NULL, DECL_MACHINE_ATTRIBUTES (decl));}/* Return nonzero if ATTR is a valid attribute for DECL.   ARGS are the arguments supplied with ATTR.  */intv850_valid_machine_decl_attribute (decl, attr, args)     tree decl;     tree attr;     tree args;{  v850_data_area data_area;  v850_data_area area;    if (args != NULL_TREE)    return 0;  if (is_attribute_p ("interrupt_handler", attr)      || is_attribute_p ("interrupt", attr))    return TREE_CODE (decl) == FUNCTION_DECL;  /* Implement data area attribute.  */  if (is_attribute_p ("sda", attr))    data_area = DATA_AREA_SDA;  else if (is_attribute_p ("tda", attr))    data_area = DATA_AREA_TDA;  else if (is_attribute_p ("zda", attr))    data_area = DATA_AREA_ZDA;  else    return 0;    switch (TREE_CODE (decl))    {    case VAR_DECL:      if (current_function_decl != NULL_TREE)	error_with_decl (decl, "\a data area attribute cannot be specified for local variables");            /* Drop through.  */

⌨️ 快捷键说明

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