m68hc11.c
来自「gcc3.2.1源代码」· C语言 代码 · 共 2,530 行 · 第 1/5 页
C
2,530 行
&& (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_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 ATTRIBUTE_UNUSED;{ 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_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;}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 }, { NULL, 0, 0, false, false, false, NULL }};/* 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) != FIELD_DECL && TREE_CODE (*node) != TYPE_DECL) { warning ("`%s' attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE;}/* Define this macro if references to a symbol must be treated differently depending on something about the variable or function named by the symbol (such as what section it is in). For the 68HC11, 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. */voidm68hc11_encode_section_info (decl) tree decl;{ tree func_attr; int trap_handler; rtx rtl; if (TREE_CODE (decl) != FUNCTION_DECL) return; rtl = DECL_RTL (decl); func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl)); trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE; SYMBOL_REF_FLAG (XEXP (rtl, 0)) = trap_handler;}/* 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)); trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE; if (trap_handler && from == ARG_POINTER_REGNUM) size = 7; 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 { 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;}/* The "standard" implementation of va_start: just assign `nextarg' to the variable. */voidm68hc11_expand_builtin_va_start (stdarg_p, valist, nextarg) int stdarg_p ATTRIBUTE_UNUSED; tree valist; rtx nextarg;{ tree t; /* SCz: the default implementation in builtins.c adjust the nextarg using UNITS_PER_WORD. This works only with -mshort and fails when integers are 32-bit. Here is the correct way. */ if (!stdarg_p) nextarg = plus_constant (nextarg, -INT_TYPE_SIZE / 8); t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, make_tree (ptr_type_node, nextarg)); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);}rtxm68hc11_va_arg (valist, type) tree valist; tree type;{ tree addr_tree, t; HOST_WIDE_INT align; HOST_WIDE_INT rounded_size; rtx addr; int pad_direction; /* Compute the rounded size of the type. */ align = PARM_BOUNDARY / BITS_PER_UNIT; rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align); /* Get AP. */ addr_tree = valist; pad_direction = m68hc11_function_arg_padding (TYPE_MODE (type), type); if (pad_direction == downward) { /* Small args are padded downward. */ HOST_WIDE_INT adj; adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT; if (rounded_size > align) adj = rounded_size; addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree, build_int_2 (rounded_size - adj, 0)); } addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL); addr = copy_to_reg (addr); /* Compute new value for AP. */ t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, build (PLUS_EXPR, TREE_TYPE (valist), valist,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?