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

📄 m68hc11.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
stack_register_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return SP_REG_P (operand);}intd_register_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_MODE (operand) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (operand) == SUBREG)    operand = XEXP (operand, 0);  return GET_CODE (operand) == REG    && (REGNO (operand) >= FIRST_PSEUDO_REGISTER	|| REGNO (operand) == HARD_D_REGNUM        || (mode == QImode && REGNO (operand) == HARD_B_REGNUM));}inthard_addr_reg_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_MODE (operand) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (operand) == SUBREG)    operand = XEXP (operand, 0);  return GET_CODE (operand) == REG    && (REGNO (operand) == HARD_X_REGNUM	|| REGNO (operand) == HARD_Y_REGNUM	|| REGNO (operand) == HARD_Z_REGNUM);}inthard_reg_operand (operand, mode)     rtx operand;     enum machine_mode mode;{  if (GET_MODE (operand) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (operand) == SUBREG)    operand = XEXP (operand, 0);  return GET_CODE (operand) == REG    && (REGNO (operand) >= FIRST_PSEUDO_REGISTER	|| H_REGNO_P (REGNO (operand)));}intmemory_indexed_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (operand) != MEM)    return 0;  operand = XEXP (operand, 0);  if (GET_CODE (operand) == PLUS)    {      if (GET_CODE (XEXP (operand, 0)) == REG)	operand = XEXP (operand, 0);      else if (GET_CODE (XEXP (operand, 1)) == REG)	operand = XEXP (operand, 1);    }  return GET_CODE (operand) == REG    && (REGNO (operand) >= FIRST_PSEUDO_REGISTER	|| A_REGNO_P (REGNO (operand)));}intpush_pop_operand_p (operand)     rtx operand;{  if (GET_CODE (operand) != MEM)    {      return 0;    }  operand = XEXP (operand, 0);  return PUSH_POP_ADDRESS_P (operand);}/* Returns 1 if OP is either a symbol reference or a sum of a symbol   reference and a constant.  */intsymbolic_memory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    case SYMBOL_REF:    case LABEL_REF:      return 1;    case CONST:      op = XEXP (op, 0);      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)	      && GET_CODE (XEXP (op, 1)) == CONST_INT);      /* ??? This clause seems to be irrelevant.  */    case CONST_DOUBLE:      return GET_MODE (op) == mode;    case PLUS:      return symbolic_memory_operand (XEXP (op, 0), mode)	&& symbolic_memory_operand (XEXP (op, 1), mode);    default:      return 0;    }}intm68hc11_eq_compare_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return GET_CODE (op) == EQ || GET_CODE (op) == NE;}intm68hc11_logical_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR;}intm68hc11_arith_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR    || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS    || GET_CODE (op) == ASHIFT || GET_CODE (op) == ASHIFTRT    || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ROTATE    || GET_CODE (op) == ROTATERT;}intm68hc11_non_shift_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR    || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS;}/* Return true if op is a shift operator.  */intm68hc11_shift_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return GET_CODE (op) == ROTATE || GET_CODE (op) == ROTATERT    || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFT    || GET_CODE (op) == ASHIFTRT;}intm68hc11_unary_operator (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return GET_CODE (op) == NEG || GET_CODE (op) == NOT    || GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;}/* Emit the code to build the trampoline used to call a nested function.      68HC11               68HC12   ldy #&CXT            movw #&CXT,*_.d1   sty *_.d1            jmp FNADDR   jmp FNADDR*/voidm68hc11_initialize_trampoline (tramp, fnaddr, cxt)     rtx tramp;     rtx fnaddr;     rtx cxt;{  const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];  /* Skip the '*'.  */  if (*static_chain_reg == '*')    static_chain_reg++;  if (TARGET_M6811)    {      emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x18ce));      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),                      GEN_INT (0x18df));      emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),                      gen_rtx_CONST (QImode,                                     gen_rtx_SYMBOL_REF (Pmode,                                                         static_chain_reg)));      emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 7)),                      GEN_INT (0x7e));      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 8)), fnaddr);    }  else    {      emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x1803));      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),                      gen_rtx_CONST (HImode,                                     gen_rtx_SYMBOL_REF (Pmode,                                                         static_chain_reg)));      emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),                      GEN_INT (0x06));      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 7)), fnaddr);    }}/* Declaration of types.  */const struct attribute_spec m68hc11_attribute_table[] ={  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */  { "interrupt", 0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },  { "trap",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },  { "far",       0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },  { "near",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },  { NULL,        0, 0, false, false, false, NULL }};/* Keep track of the symbol which has a `trap' attribute and which uses   the `swi' calling convention.  Since there is only one trap, we only   record one such symbol.  If there are several, a warning is reported.  */static rtx trap_handler_symbol = 0;/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;   arguments as in struct attribute_spec.handler.  */static treem68hc11_handle_fntype_attribute (node, name, args, flags, no_add_attrs)     tree *node;     tree name;     tree args ATTRIBUTE_UNUSED;     int flags ATTRIBUTE_UNUSED;     bool *no_add_attrs;{  if (TREE_CODE (*node) != FUNCTION_TYPE      && TREE_CODE (*node) != METHOD_TYPE      && TREE_CODE (*node) != FIELD_DECL      && TREE_CODE (*node) != TYPE_DECL)    {      warning ("`%s' attribute only applies to functions",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}/* We want to recognize trap handlers so that we handle calls to traps   in a special manner (by issuing the trap).  This information is stored   in SYMBOL_REF_FLAG.  */static voidm68hc11_encode_section_info (decl, first)     tree decl;     int first ATTRIBUTE_UNUSED;{  tree func_attr;  int trap_handler;  int is_far = 0;  rtx rtl;    if (TREE_CODE (decl) != FUNCTION_DECL)    return;  rtl = DECL_RTL (decl);  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;}intm68hc11_is_far_symbol (sym)     rtx sym;{  if (GET_CODE (sym) == MEM)    sym = XEXP (sym, 0);  return SYMBOL_REF_FLAG (sym);}intm68hc11_is_trap_symbol (sym)     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.  *//* Handle the FUNCTION_ARG_PASS_BY_REFERENCE macro.   Arrays are passed by references and other types by value.   SCz: I tried to pass DImode by reference but it seems that this   does not work very well.  */intm68hc11_function_arg_pass_by_reference (cum, mode, type, named)     const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;     enum machine_mode mode ATTRIBUTE_UNUSED;     tree type;     int named ATTRIBUTE_UNUSED;{  return ((type && TREE_CODE (type) == ARRAY_TYPE)	  /* Consider complex values as aggregates, so care for TCmode.  */	  /*|| GET_MODE_SIZE (mode) > 4 SCz, temporary */	  /*|| (type && AGGREGATE_TYPE_P (type))) */ );}/* 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 (from, to)     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));  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;  trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;  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 (cum, fntype, libname)     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))    {      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 (cum, mode, type, named)     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    {

⌨️ 快捷键说明

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