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

📄 m68hc11.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));  if (lookup_attribute ("far", func_attr) != NULL_TREE)    is_far = 1;  else if (lookup_attribute ("near", func_attr) == NULL_TREE)    is_far = TARGET_LONG_CALLS != 0;  trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;  if (trap_handler && is_far)    {      warning ("%<trap%> and %<far%> attributes are not compatible, ignoring %<far%>");      trap_handler = 0;    }  if (trap_handler)    {      if (trap_handler_symbol != 0)        warning ("%<trap%> attribute is already used");      else        trap_handler_symbol = XEXP (rtl, 0);    }  SYMBOL_REF_FLAG (XEXP (rtl, 0)) = is_far;}static unsigned intm68hc11_section_type_flags (tree decl, const char *name, int reloc){  unsigned int flags = default_section_type_flags (decl, name, reloc);  if (strncmp (name, ".eeprom", 7) == 0)    {      flags |= SECTION_WRITE | SECTION_CODE | SECTION_OVERRIDE;    }  return flags;}intm68hc11_is_far_symbol (rtx sym){  if (GET_CODE (sym) == MEM)    sym = XEXP (sym, 0);  return SYMBOL_REF_FLAG (sym);}intm68hc11_is_trap_symbol (rtx sym){  if (GET_CODE (sym) == MEM)    sym = XEXP (sym, 0);  return trap_handler_symbol != 0 && rtx_equal_p (trap_handler_symbol, sym);}/* Argument support functions.  *//* Define the offset between two registers, one to be eliminated, and the   other its replacement, at the start of a routine.  */intm68hc11_initial_elimination_offset (int from, int to){  int trap_handler;  tree func_attr;  int size;  int regno;  /* For a trap handler, we must take into account the registers which     are pushed on the stack during the trap (except the PC).  */  func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));  current_function_interrupt = lookup_attribute ("interrupt",						 func_attr) != NULL_TREE;  trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;  if (lookup_attribute ("far", func_attr) != 0)    current_function_far = 1;  else if (lookup_attribute ("near", func_attr) != 0)    current_function_far = 0;  else    current_function_far = (TARGET_LONG_CALLS != 0                            && !current_function_interrupt                            && !trap_handler);  if (trap_handler && from == ARG_POINTER_REGNUM)    size = 7;  /* For a function using 'call/rtc' we must take into account the     page register which is pushed in the call.  */  else if (current_function_far && from == ARG_POINTER_REGNUM)    size = 1;  else    size = 0;  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)    {      /* 2 is for the saved frame.         1 is for the 'sts' correction when creating the frame.  */      return get_frame_size () + 2 + m68hc11_sp_correction + size;    }  if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)    {      return m68hc11_sp_correction;    }  /* Push any 2 byte pseudo hard registers that we need to save.  */  for (regno = SOFT_REG_FIRST; regno < SOFT_REG_LAST; regno++)    {      if (regs_ever_live[regno] && !call_used_regs[regno])	{	  size += 2;	}    }  if (from == ARG_POINTER_REGNUM && to == HARD_SP_REGNUM)    {      return get_frame_size () + size;    }  if (from == FRAME_POINTER_REGNUM && to == HARD_SP_REGNUM)    {      return size;    }  return 0;}/* Initialize a variable CUM of type CUMULATIVE_ARGS   for a call to a function whose data type is FNTYPE.   For a library call, FNTYPE is 0.  */voidm68hc11_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname){  tree ret_type;  z_replacement_completed = 0;  cum->words = 0;  cum->nregs = 0;  /* For a library call, we must find out the type of the return value.     When the return value is bigger than 4 bytes, it is returned in     memory.  In that case, the first argument of the library call is a     pointer to the memory location.  Because the first argument is passed in     register D, we have to identify this, so that the first function     parameter is not passed in D either.  */  if (fntype == 0)    {      const char *name;      size_t len;      if (libname == 0 || GET_CODE (libname) != SYMBOL_REF)	return;      /* If the library ends in 'di' or in 'df', we assume it's         returning some DImode or some DFmode which are 64-bit wide.  */      name = XSTR (libname, 0);      len = strlen (name);      if (len > 3	  && ((name[len - 2] == 'd'	       && (name[len - 1] == 'f' || name[len - 1] == 'i'))	      || (name[len - 3] == 'd'		  && (name[len - 2] == 'i' || name[len - 2] == 'f'))))	{	  /* We are in.  Mark the first parameter register as already used.  */	  cum->words = 1;	  cum->nregs = 1;	}      return;    }  ret_type = TREE_TYPE (fntype);  if (ret_type && aggregate_value_p (ret_type, fntype))    {      cum->words = 1;      cum->nregs = 1;    }}/* Update the data in CUM to advance over an argument   of mode MODE and data type TYPE.   (TYPE is null for libcalls where that information may not be available.)  */voidm68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,                              tree type, int named ATTRIBUTE_UNUSED){  if (mode != BLKmode)    {      if (cum->words == 0 && GET_MODE_SIZE (mode) == 4)	{	  cum->nregs = 2;	  cum->words = GET_MODE_SIZE (mode);	}      else	{	  cum->words += GET_MODE_SIZE (mode);	  if (cum->words <= HARD_REG_SIZE)	    cum->nregs = 1;	}    }  else    {      cum->words += int_size_in_bytes (type);    }  return;}/* Define where to put the arguments to a function.   Value is zero to push the argument on the stack,   or a hard register in which to store the argument.   MODE is the argument's machine mode.   TYPE is the data type of the argument (as a tree).    This is null for libcalls where that information may    not be available.   CUM is a variable of type CUMULATIVE_ARGS which gives info about    the preceding args and about the function being called.   NAMED is nonzero if this argument is a named parameter    (otherwise it is an extra parameter matching an ellipsis).  */struct rtx_def *m68hc11_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,                      tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED){  if (cum->words != 0)    {      return NULL_RTX;    }  if (mode != BLKmode)    {      if (GET_MODE_SIZE (mode) == 2 * HARD_REG_SIZE)	return gen_rtx_REG (mode, HARD_X_REGNUM);      if (GET_MODE_SIZE (mode) > HARD_REG_SIZE)	{	  return NULL_RTX;	}      return gen_rtx_REG (mode, HARD_D_REGNUM);    }  return NULL_RTX;}/* If defined, a C expression which determines whether, and in which direction,   to pad out an argument with extra space.  The value should be of type   `enum direction': either `upward' to pad above the argument,   `downward' to pad below, or `none' to inhibit padding.   Structures are stored left shifted in their argument slot.  */intm68hc11_function_arg_padding (enum machine_mode mode, tree type){  if (type != 0 && AGGREGATE_TYPE_P (type))    return upward;  /* Fall back to the default.  */  return DEFAULT_FUNCTION_ARG_PADDING (mode, type);}/* Function prologue and epilogue.  *//* Emit a move after the reload pass has completed.  This is used to   emit the prologue and epilogue.  */static voidemit_move_after_reload (rtx to, rtx from, rtx scratch){  rtx insn;  if (TARGET_M6812 || H_REG_P (to) || H_REG_P (from))    {      insn = emit_move_insn (to, from);    }  else    {      emit_move_insn (scratch, from);      insn = emit_move_insn (to, scratch);    }  /* Put a REG_INC note to tell the flow analysis that the instruction     is necessary.  */  if (IS_STACK_PUSH (to))    {      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,					    XEXP (XEXP (to, 0), 0),					    REG_NOTES (insn));    }  else if (IS_STACK_POP (from))    {      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,					    XEXP (XEXP (from, 0), 0),					    REG_NOTES (insn));    }  /* For 68HC11, put a REG_INC note on `sts _.frame' to prevent the cse-reg     to think that sp == _.frame and later replace a x = sp with x = _.frame.     The problem is that we are lying to gcc and use `txs' for x = sp     (which is not really true because txs is really x = sp + 1).  */  else if (TARGET_M6811 && SP_REG_P (from))    {      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,					    from,					    REG_NOTES (insn));    }}intm68hc11_total_frame_size (void){  int size;  int regno;  size = get_frame_size ();  if (current_function_interrupt)    {      size += 3 * HARD_REG_SIZE;    }  if (frame_pointer_needed)    size += HARD_REG_SIZE;  for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)    if (regs_ever_live[regno] && !call_used_regs[regno])      size += HARD_REG_SIZE;  return size;}static voidm68hc11_output_function_epilogue (FILE *out ATTRIBUTE_UNUSED,                                  HOST_WIDE_INT size ATTRIBUTE_UNUSED){  /* We catch the function epilogue generation to have a chance     to clear the z_replacement_completed flag.  */  z_replacement_completed = 0;}voidexpand_prologue (void){  tree func_attr;  int size;  int regno;  rtx scratch;  if (reload_completed != 1)    abort ();  size = get_frame_size ();  create_regs_rtx ();  /* Generate specific prologue for interrupt handlers.  */  func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));  current_function_interrupt = lookup_attribute ("interrupt",						 func_attr) != NULL_TREE;  current_function_trap = lookup_attribute ("trap", func_attr) != NULL_TREE;  if (lookup_attribute ("far", func_attr) != NULL_TREE)    current_function_far = 1;  else if (lookup_attribute ("near", func_attr) != NULL_TREE)    current_function_far = 0;  else    current_function_far = (TARGET_LONG_CALLS != 0                            && !current_function_interrupt                            && !current_function_trap);  /* Get the scratch register to build the frame and push registers.     If the first argument is a 32-bit quantity, the D+X registers     are used.  Use Y to compute the frame.  Otherwise, X is cheaper.     For 68HC12, this scratch register is not used.  */  if (current_function_args_info.nregs == 2)    scratch = iy_reg;  else    scratch = ix_reg;  /* Save current stack frame.  */  if (frame_pointer_needed)    emit_move_after_reload (stack_push_word, hard_frame_pointer_rtx, scratch);  /* For an interrupt handler, we must preserve _.tmp, _.z and _.xy.     Other soft registers in page0 need not to be saved because they     will be restored by C functions.  For a trap handler, we don't     need to preserve these registers because this is a synchronous call.  */  if (current_function_interrupt)    {      emit_move_after_reload (stack_push_word, m68hc11_soft_tmp_reg, scratch);      emit_move_after_reload (stack_push_word,			      gen_rtx_REG (HImode, SOFT_Z_REGNUM), scratch);      emit_move_after_reload (stack_push_word,			      gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),			      scratch);    }  /* Allocate local variables.  */  if (TARGET_M6812 && (size > 4 || size == 3))    {      emit_insn (gen_addhi3 (stack_pointer_rtx,			     stack_pointer_rtx, GEN_INT (-size)));    }  else if ((!optimize_size && size > 8) || (optimize_size && size > 10))    {      rtx insn;      insn = gen_rtx_PARALLEL	(VOIDmode,	 gen_rtvec (2,		    gen_rtx_SET (VOIDmode,				 stack_pointer_rtx,				 gen_rtx_PLUS (HImode,					       stack_pointer_rtx,					       GEN_INT (-size))),		    gen_rtx_CLOBBER (VOIDmode, scratch)));      emit_insn (insn);    }  else    {      int i;      /* Allocate by pushing scratch values.  */      for (i = 2; i <= size; i += 2)	emit_move_after_reload (stack_push_word, ix_reg, 0);      if (size & 1)	emit_insn (gen_addhi3 (stack_pointer_rtx,			       stack_pointer_rtx, constm1_rtx));    }  /* Create the frame pointer.  */  if (frame_pointer_needed)    emit_move_after_reload (hard_frame_pointer_rtx,			    stack_pointer_rtx, scratch);  /* Push any 2 byte pseudo hard registers that we need to save.  */  for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)    {      if (regs_ever_live[regno] && !call_used_regs[regno])	{	  emit_move_after_reload (stack_push_word,				  gen_rtx_REG (HImode, regno), scratch);	}    }}voidexpand_epilogue (void){  int size;  register int regno;  int return_size;  rtx scratch;  if (reload_completed != 1)    abort ();  size = get_frame_size ();  /* If we are returning a value in two registers, we have to preserve the     X register and use the Y register to restore the stack and the saved     registers.  Otherwise, use X because it's faster (and smaller).  */  if (current_function_return_rtx == 0)    return_size = 0;  else if (GET_CODE (current_function_return_rtx) == MEM)    return_size = HARD_REG_SIZE;  else    return_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));  if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE)    scratch = iy_reg;  else    scratch = ix_reg;  /* Pop any 2 byte pseudo hard registers that we saved.  */  for (regno = SOFT_REG_LAST; regno >= SOFT_REG_FIRST; regno--)    {      if (regs_ever_live[regno] && !call_used_regs[regno])

⌨️ 快捷键说明

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