📄 m68hc11.c
字号:
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 + -