📄 m68hc11.c
字号:
}/* Returns true if X is a PRE/POST increment decrement (same as auto_inc_p() in rtlanal.c but do not take into account the stack). */static intm68hc11_auto_inc_p (rtx x){ return GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_INC;}/* Predicates for machine description. */intmemory_reload_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED){ return GET_CODE (operand) == MEM && GET_CODE (XEXP (operand, 0)) == PLUS && ((GET_CODE (XEXP (XEXP (operand, 0), 0)) == REG && GET_CODE (XEXP (XEXP (operand, 0), 1)) == CONST_INT) || (GET_CODE (XEXP (XEXP (operand, 0), 1)) == REG && GET_CODE (XEXP (XEXP (operand, 0), 0)) == CONST_INT));}inttst_operand (rtx operand, enum machine_mode mode){ if (GET_CODE (operand) == MEM && reload_completed == 0) { rtx addr = XEXP (operand, 0); if (m68hc11_auto_inc_p (addr)) return 0; } return nonimmediate_operand (operand, mode);}intcmp_operand (rtx operand, enum machine_mode mode){ if (GET_CODE (operand) == MEM) { rtx addr = XEXP (operand, 0); if (m68hc11_auto_inc_p (addr)) return 0; } return general_operand (operand, mode);}intnon_push_operand (rtx operand, enum machine_mode mode){ if (general_operand (operand, mode) == 0) return 0; if (push_operand (operand, mode) == 1) return 0; return 1;}intsplitable_operand (rtx operand, enum machine_mode mode){ if (general_operand (operand, mode) == 0) return 0; if (push_operand (operand, mode) == 1) return 0; /* Reject a (MEM (MEM X)) because the patterns that use non_push_operand need to split such addresses to access the low and high part but it is not possible to express a valid address for the low part. */ if (mode != QImode && GET_CODE (operand) == MEM && GET_CODE (XEXP (operand, 0)) == MEM) return 0; return 1;}intreg_or_some_mem_operand (rtx operand, enum machine_mode mode){ if (GET_CODE (operand) == MEM) { rtx op = XEXP (operand, 0); int addr_mode; if (symbolic_memory_operand (op, mode)) return 1; if (IS_STACK_PUSH (operand)) return 1; if (GET_CODE (operand) == REG && reload_in_progress && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_equiv_memory_loc[REGNO (operand)]) { operand = reg_equiv_memory_loc[REGNO (operand)]; operand = eliminate_regs (operand, 0, NULL_RTX); } if (GET_CODE (operand) != MEM) return 0; operand = XEXP (operand, 0); addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); addr_mode &= ~ADDR_INDIRECT; return register_indirect_p (operand, mode, addr_mode); } return register_operand (operand, mode);}intm68hc11_symbolic_p (rtx operand, enum machine_mode mode){ if (GET_CODE (operand) == MEM) { rtx op = XEXP (operand, 0); if (symbolic_memory_operand (op, mode)) return 1; } return 0;}intm68hc11_indirect_p (rtx operand, enum machine_mode mode){ if (GET_CODE (operand) == MEM && GET_MODE (operand) == mode) { rtx op = XEXP (operand, 0); int addr_mode; if (m68hc11_page0_symbol_p (op)) return 1; if (symbolic_memory_operand (op, mode)) return TARGET_M6812; if (reload_in_progress) return 1; operand = XEXP (operand, 0); addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); return register_indirect_p (operand, mode, addr_mode); } return 0;}intstack_register_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED){ return SP_REG_P (operand);}intd_register_operand (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 || REGNO (operand) == HARD_D_REGNUM || (mode == QImode && REGNO (operand) == HARD_B_REGNUM));}inthard_addr_reg_operand (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) == HARD_X_REGNUM || REGNO (operand) == HARD_Y_REGNUM || REGNO (operand) == HARD_Z_REGNUM);}inthard_reg_operand (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 (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 (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 (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 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return GET_CODE (op) == EQ || GET_CODE (op) == NE;}intm68hc11_logical_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR;}intm68hc11_arith_operator (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 (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 (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 (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 (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. *//* Handle an "tiny_data" attribute; arguments as in struct attribute_spec.handler. */static treem68hc11_handle_page0_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs){ tree decl = *node; if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) { DECL_SECTION_NAME (decl) = build_string (6, ".page0"); } else { warning ("%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE;}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 }, { "page0", 0, 0, false, false, false, m68hc11_handle_page0_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 (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 ("%qs attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE;}/* Undo the effects of the above. */static const char *m68hc11_strip_name_encoding (const char *str){ return str + (*str == '*' || *str == '@' || *str == '&');}static voidm68hc11_encode_label (tree decl){ const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0); int len = strlen (str); char *newstr = alloca (len + 2); newstr[0] = '@'; strcpy (&newstr[1], str); XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 1);}/* Return 1 if this is a symbol in page0 */intm68hc11_page0_symbol_p (rtx x){ switch (GET_CODE (x)) { case SYMBOL_REF: return XSTR (x, 0) != 0 && XSTR (x, 0)[0] == '@'; case CONST: return m68hc11_page0_symbol_p (XEXP (x, 0)); case PLUS: if (!m68hc11_page0_symbol_p (XEXP (x, 0))) return 0; return GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) < 256 && INTVAL (XEXP (x, 1)) >= 0; default: return 0; }}/* 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 (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED){ tree func_attr; int trap_handler; int is_far = 0; if (TREE_CODE (decl) == VAR_DECL) { if (lookup_attribute ("page0", DECL_ATTRIBUTES (decl)) != 0) m68hc11_encode_label (decl); return; } if (TREE_CODE (decl) != FUNCTION_DECL) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -