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

📄 m68hc11.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
      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 (cum, mode, type, named)     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 (mode, type)     enum machine_mode mode;     tree type;{  if (type != 0 && AGGREGATE_TYPE_P (type))    return upward;  /* This is the default definition.  */  return (!BYTES_BIG_ENDIAN	  ? upward	  : ((mode == BLKmode	      ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST		 && int_size_in_bytes (type) <		 (PARM_BOUNDARY / BITS_PER_UNIT)) : GET_MODE_BITSIZE (mode) <	      PARM_BOUNDARY) ? downward : upward));}/* 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 (to, from, scratch)     rtx to, from, 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 (){  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 (out, size)     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 (){  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;  /* 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, GEN_INT (-1)));    }  /* 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 (){  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])	{	  emit_move_after_reload (gen_rtx (REG, HImode, regno),				  stack_pop_word, scratch);	}    }  /* de-allocate auto 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;      for (i = 2; i <= size; i += 2)	emit_move_after_reload (scratch, stack_pop_word, scratch);      if (size & 1)	emit_insn (gen_addhi3 (stack_pointer_rtx,			       stack_pointer_rtx, GEN_INT (1)));    }  /* For an interrupt handler, restore ZTMP, ZREG and XYREG.  */  if (current_function_interrupt)    {      emit_move_after_reload (gen_rtx (REG, HImode, SOFT_SAVED_XY_REGNUM),			      stack_pop_word, scratch);      emit_move_after_reload (gen_rtx (REG, HImode, SOFT_Z_REGNUM),			      stack_pop_word, scratch);      emit_move_after_reload (m68hc11_soft_tmp_reg, stack_pop_word, scratch);    }  /* Restore previous frame pointer.  */  if (frame_pointer_needed)    emit_move_after_reload (hard_frame_pointer_rtx, stack_pop_word, scratch);  /* If the trap handler returns some value, copy the value     in D, X onto the stack so that the rti will pop the return value     correctly.  */  else if (current_function_trap && return_size != 0)    {      rtx addr_reg = stack_pointer_rtx;      if (!TARGET_M6812)	{	  emit_move_after_reload (scratch, stack_pointer_rtx, 0);	  addr_reg = scratch;	}      emit_move_after_reload (gen_rtx (MEM, HImode,				       gen_rtx (PLUS, HImode, addr_reg,						GEN_INT (1))), d_reg, 0);      if (return_size > HARD_REG_SIZE)	emit_move_after_reload (gen_rtx (MEM, HImode,					 gen_rtx (PLUS, HImode, addr_reg,						  GEN_INT (3))), ix_reg, 0);    }  emit_jump_insn (gen_return ());}/* Low and High part extraction for 68HC11.  These routines are   similar to gen_lowpart and gen_highpart but they have been   fixed to work for constants and 68HC11 specific registers.  */rtxm68hc11_gen_lowpart (mode, x)     enum machine_mode mode;     rtx x;{  /* We assume that the low part of an auto-inc mode is the same with     the mode changed and that the caller split the larger mode in the     correct order.  */  if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))    {      return gen_rtx (MEM, mode, XEXP (x, 0));    }  /* Note that a CONST_DOUBLE rtx could represent either an integer or a     floating-point constant.  A CONST_DOUBLE is used whenever the     constant requires more than one word in order to be adequately     represented.  */  if (GET_CODE (x) == CONST_DOUBLE)    {      long l[2];      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	{	  REAL_VALUE_TYPE r;	  if (GET_MODE (x) == SFmode)	    {	      REAL_VALUE_FROM_CONST_DOUBLE (r, x);	      REAL_VALUE_TO_TARGET_SINGLE (r, l[0]);	    }	  else	    {	      rtx first, second;	      split_double (x, &first, &second);	      return second;	    }	  if (mode == SImode)	    return GEN_INT (l[0]);	  return gen_int_mode (l[0], HImode);	}      else	{	  l[0] = CONST_DOUBLE_LOW (x);	}      if (mode == SImode)	return GEN_INT (l[0]);      else if (mode == HImode && GET_MODE (x) == SFmode)	return gen_int_mode (l[0], HImode);      else	abort ();    }  if (mode == QImode && D_REG_P (x))    return gen_rtx (REG, mode, HARD_B_REGNUM);  /* gen_lowpart crashes when it is called with a SUBREG.  */  if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)    {      if (mode == SImode)	return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4);      else if (mode == HImode)	return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);      else	abort ();    }  x = gen_lowpart (mode, x);  /* Return a different rtx to avoid to share it in several insns     (when used by a split pattern).  Sharing addresses within     a MEM breaks the Z register replacement (and reloading).  */  if (GET_CODE (x) == MEM)    x = copy_rtx (x);  return x;}rtxm68hc11_gen_highpart (mode, x)     enum machine_mode mode;     rtx x;{  /* We assume that the high part of an auto-inc mode is the same with     the mode changed and that the caller split the larger mode in the     correct order.  */  if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))    {      return gen_rtx (MEM, mode, XEXP (x, 0));    }  /* Note that a CONST_DOUBLE rtx could represent either an integer or a     floating-point constant.  A CONST_DOUBLE is used whenever the     constant requires more than one word in order to be adequately     represented.  */  if (GET_CODE (x) == CONST_DOUBLE)    {      long l[2];      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	{	  REAL_VALUE_TYPE r;	  if (GET_MODE (x) == SFmode)	    {	      REAL_VALUE_FROM_CONST_DOUBLE (r, x);	      REAL_VALUE_TO_TARGET_SINGLE (r, l[1]);	    }	  else	    {	      rtx first, second;	      split_double (x, &first, &second);	      return first;	    }	  if (mode == SImode)	    return GEN_INT (l[1]);	  return gen_int_mode ((l[1] >> 16), HImode);	}      else	{	  l[1] = CONST_DOUBLE_HIGH (x);	}      if (mode == SImode)	return GEN_INT (l[1]);      else if (mode == HImode && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	return gen_int_mode ((l[0] >> 16), HImode);      else	abort ();    }  if (GET_CODE (x) == CONST_INT)    {      HOST_WIDE_INT val = INTVAL (x);      if (mode == QImode)	{	  return gen_int_mode (val >> 8, QImode);	}

⌨️ 快捷键说明

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