X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fconfig%2Fm68hc11%2Fm68hc11.c;h=e45a74892c6471b45be515bad178c279a16e2a6e;hb=5bd84829f73d467f67746090cd781973d674f2f3;hp=93fe2c3d9ad7dcb91dcf82663d22bb2ce92a763a;hpb=a0cd568f5935e52a2c19b21b78bea7c1296745b6;p=gcc.git diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index 93fe2c3d9ad..e45a74892c6 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -1,13 +1,13 @@ /* Subroutines for code generation on Motorola 68HC11 and 68HC12. - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010 Free Software Foundation, Inc. Contributed by Stephane Carrez (stcarrez@nerim.fr) This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, @@ -16,9 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. +along with GCC; see the file COPYING3. If not see +. Note: A first 68HC11 port was made by Otto Lind (otto@coactive.com) @@ -40,10 +39,10 @@ Note: #include "tm.h" #include "rtl.h" #include "tree.h" +#include "expr.h" #include "tm_p.h" #include "regs.h" #include "hard-reg-set.h" -#include "real.h" #include "insn-config.h" #include "conditions.h" #include "output.h" @@ -52,6 +51,7 @@ Note: #include "recog.h" #include "expr.h" #include "libfuncs.h" +#include "diagnostic-core.h" #include "toplev.h" #include "basic-block.h" #include "function.h" @@ -59,25 +59,30 @@ Note: #include "reload.h" #include "target.h" #include "target-def.h" +#include "df.h" +static void m68hc11_option_override (void); static void emit_move_after_reload (rtx, rtx, rtx); static rtx simplify_logical (enum machine_mode, int, rtx, rtx *); -static void m68hc11_emit_logical (enum machine_mode, int, rtx *); +static void m68hc11_emit_logical (enum machine_mode, enum rtx_code, rtx *); static void m68hc11_reorg (void); -static int go_if_legitimate_address_internal (rtx, enum machine_mode, int); -static int register_indirect_p (rtx, enum machine_mode, int); +static bool m68hc11_legitimate_address_p_1 (enum machine_mode, rtx, bool); +static bool m68hc11_legitimate_address_p (enum machine_mode, rtx, bool); static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx); static int must_parenthesize (rtx); -static int m68hc11_address_cost (rtx); +static int m68hc11_address_cost (rtx, bool); static int m68hc11_shift_cost (enum machine_mode, rtx, int); static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code); -static bool m68hc11_rtx_costs (rtx, int, int, int *); +static bool m68hc11_rtx_costs (rtx, int, int, int *, bool); static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *); -const struct attribute_spec m68hc11_attribute_table[]; +static tree m68hc11_handle_page0_attribute (tree *, tree, tree, int, bool *); +static bool m68hc11_class_likely_spilled_p (reg_class_t); void create_regs_rtx (void); static void asm_print_register (FILE *, int); +static void m68hc11_print_operand (FILE *, rtx, int); +static void m68hc11_print_operand_address (FILE *, rtx); static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT); static void m68hc11_asm_out_constructor (rtx, int); static void m68hc11_asm_out_destructor (rtx, int); @@ -89,7 +94,9 @@ static int autoinc_mode (rtx); static int m68hc11_make_autoinc_notes (rtx *, void *); static void m68hc11_init_libfuncs (void); static rtx m68hc11_struct_value_rtx (tree, int); -static bool m68hc11_return_in_memory (tree, tree); +static bool m68hc11_return_in_memory (const_tree, const_tree); +static bool m68hc11_can_eliminate (const int, const int); +static void m68hc11_trampoline_init (rtx, tree, rtx); /* Must be set to 1 to produce debug messages. */ int debug_m6811 = 0; @@ -140,19 +147,8 @@ unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER]; This is 1 for 68HC11 and 0 for 68HC12. */ int m68hc11_sp_correction; -#define ADDR_STRICT 0x01 /* Accept only registers in class A_REGS */ -#define ADDR_INCDEC 0x02 /* Post/Pre inc/dec */ -#define ADDR_INDEXED 0x04 /* D-reg index */ -#define ADDR_OFFSET 0x08 -#define ADDR_INDIRECT 0x10 /* Accept (mem (mem ...)) for [n,X] */ -#define ADDR_CONST 0x20 /* Accept const and symbol_ref */ - int m68hc11_addr_mode; int m68hc11_mov_addr_mode; - -/* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns. */ -rtx m68hc11_compare_op0; -rtx m68hc11_compare_op1; const struct processor_costs *m68hc11_cost; @@ -227,6 +223,19 @@ static const struct processor_costs m6812_cost = { COSTS_N_INSNS (100) }; +/* M68HC11 specific attributes. */ + +static 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 } +}; + /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table @@ -234,6 +243,11 @@ static const struct processor_costs m6812_cost = { #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" +#undef TARGET_PRINT_OPERAND +#define TARGET_PRINT_OPERAND m68hc11_print_operand +#undef TARGET_PRINT_OPERAND_ADDRESS +#define TARGET_PRINT_OPERAND_ADDRESS m68hc11_print_operand_address + #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue @@ -272,10 +286,25 @@ static const struct processor_costs m6812_cost = { #undef TARGET_STRIP_NAME_ENCODING #define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encoding +#undef TARGET_LEGITIMATE_ADDRESS_P +#define TARGET_LEGITIMATE_ADDRESS_P m68hc11_legitimate_address_p + +#undef TARGET_CAN_ELIMINATE +#define TARGET_CAN_ELIMINATE m68hc11_can_eliminate + +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P m68hc11_class_likely_spilled_p + +#undef TARGET_TRAMPOLINE_INIT +#define TARGET_TRAMPOLINE_INIT m68hc11_trampoline_init + +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE m68hc11_option_override + struct gcc_target targetm = TARGET_INITIALIZER; -int -m68hc11_override_options (void) +static void +m68hc11_option_override (void) { memset (m68hc11_reg_valid_for_index, 0, sizeof (m68hc11_reg_valid_for_index)); @@ -340,7 +369,6 @@ m68hc11_override_options (void) if (TARGET_LONG_CALLS) current_function_far = 1; } - return 0; } @@ -390,9 +418,9 @@ create_regs_rtx (void) } /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - - 8 bit values are stored anywhere (except the SP register). - - 16 bit values can be stored in any register whose mode is 16 - - 32 bit values can be stored in D, X registers or in a soft register + - 8-bit values are stored anywhere (except the SP register). + - 16-bit values can be stored in any register whose mode is 16 + - 32-bit values can be stored in D, X registers or in a soft register (except the last one because we need 2 soft registers) - Values whose size is > 32 bit are not stored in real hard registers. They may be stored in soft registers if there are @@ -443,7 +471,7 @@ m68hc11_hard_regno_rename_ok (int reg1, int reg2) } enum reg_class -preferred_reload_class (rtx operand, enum reg_class class) +preferred_reload_class (rtx operand, enum reg_class rclass) { enum machine_mode mode; @@ -451,97 +479,97 @@ preferred_reload_class (rtx operand, enum reg_class class) if (debug_m6811) { - printf ("Preferred reload: (class=%s): ", reg_class_names[class]); + printf ("Preferred reload: (class=%s): ", reg_class_names[rclass]); } - if (class == D_OR_A_OR_S_REGS && SP_REG_P (operand)) + if (rclass == D_OR_A_OR_S_REGS && SP_REG_P (operand)) return m68hc11_base_reg_class; - if (class >= S_REGS && (GET_CODE (operand) == MEM + if (rclass >= S_REGS && (GET_CODE (operand) == MEM || GET_CODE (operand) == CONST_INT)) { /* S_REGS class must not be used. The movhi template does not work to move a memory to a soft register. Restrict to a hard reg. */ - switch (class) + switch (rclass) { default: case G_REGS: case D_OR_A_OR_S_REGS: - class = A_OR_D_REGS; + rclass = A_OR_D_REGS; break; case A_OR_S_REGS: - class = A_REGS; + rclass = A_REGS; break; case D_OR_SP_OR_S_REGS: - class = D_OR_SP_REGS; + rclass = D_OR_SP_REGS; break; case D_OR_Y_OR_S_REGS: - class = D_OR_Y_REGS; + rclass = D_OR_Y_REGS; break; case D_OR_X_OR_S_REGS: - class = D_OR_X_REGS; + rclass = D_OR_X_REGS; break; case SP_OR_S_REGS: - class = SP_REGS; + rclass = SP_REGS; break; case Y_OR_S_REGS: - class = Y_REGS; + rclass = Y_REGS; break; case X_OR_S_REGS: - class = X_REGS; + rclass = X_REGS; break; case D_OR_S_REGS: - class = D_REGS; + rclass = D_REGS; } } - else if (class == Y_REGS && GET_CODE (operand) == MEM) + else if (rclass == Y_REGS && GET_CODE (operand) == MEM) { - class = Y_REGS; + rclass = Y_REGS; } - else if (class == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4) + else if (rclass == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4) { - class = D_OR_X_REGS; + rclass = D_OR_X_REGS; } - else if (class >= S_REGS && S_REG_P (operand)) + else if (rclass >= S_REGS && S_REG_P (operand)) { - switch (class) + switch (rclass) { default: case G_REGS: case D_OR_A_OR_S_REGS: - class = A_OR_D_REGS; + rclass = A_OR_D_REGS; break; case A_OR_S_REGS: - class = A_REGS; + rclass = A_REGS; break; case D_OR_SP_OR_S_REGS: - class = D_OR_SP_REGS; + rclass = D_OR_SP_REGS; break; case D_OR_Y_OR_S_REGS: - class = D_OR_Y_REGS; + rclass = D_OR_Y_REGS; break; case D_OR_X_OR_S_REGS: - class = D_OR_X_REGS; + rclass = D_OR_X_REGS; break; case SP_OR_S_REGS: - class = SP_REGS; + rclass = SP_REGS; break; case Y_OR_S_REGS: - class = Y_REGS; + rclass = Y_REGS; break; case X_OR_S_REGS: - class = X_REGS; + rclass = X_REGS; break; case D_OR_S_REGS: - class = D_REGS; + rclass = D_REGS; } } - else if (class >= S_REGS) + else if (rclass >= S_REGS) { if (debug_m6811) { - printf ("Class = %s for: ", reg_class_names[class]); + printf ("Class = %s for: ", reg_class_names[rclass]); fflush (stdout); debug_rtx (operand); } @@ -549,19 +577,45 @@ preferred_reload_class (rtx operand, enum reg_class class) if (debug_m6811) { - printf (" => class=%s\n", reg_class_names[class]); + printf (" => class=%s\n", reg_class_names[rclass]); fflush (stdout); debug_rtx (operand); } - return class; + return rclass; +} + +/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */ + +static bool +m68hc11_class_likely_spilled_p (reg_class_t rclass) +{ + switch (rclass) + { + case D_REGS: + case X_REGS: + case Y_REGS: + case A_REGS: + case SP_REGS: + case D_OR_X_REGS: + case D_OR_Y_REGS: + case X_OR_SP_REGS: + case Y_OR_SP_REGS: + case D_OR_SP_REGS: + return true; + + default: + break; + } + + return false; } /* Return 1 if the operand is a valid indexed addressing mode. For 68hc11: n,r with n in [0..255] and r in A_REGS class For 68hc12: n,r no constraint on the constant, r in A_REGS class. */ -static int -register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode) +int +m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode) { rtx base, offset; @@ -569,8 +623,8 @@ register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode) { case MEM: if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2) - return register_indirect_p (XEXP (operand, 0), mode, - addr_mode & (ADDR_STRICT | ADDR_OFFSET)); + return m68hc11_valid_addressing_p (XEXP (operand, 0), mode, + addr_mode & (ADDR_STRICT | ADDR_OFFSET)); return 0; case POST_INC: @@ -578,8 +632,8 @@ register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode) case POST_DEC: case PRE_DEC: if (addr_mode & ADDR_INCDEC) - return register_indirect_p (XEXP (operand, 0), mode, - addr_mode & ADDR_STRICT); + return m68hc11_valid_addressing_p (XEXP (operand, 0), mode, + addr_mode & ADDR_STRICT); return 0; case PLUS: @@ -661,7 +715,7 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode) && reg_equiv_memory_loc[REGNO (operand)]) { operand = reg_equiv_memory_loc[REGNO (operand)]; - operand = eliminate_regs (operand, 0, NULL_RTX); + operand = eliminate_regs (operand, VOIDmode, NULL_RTX); } if (GET_CODE (operand) != MEM) @@ -675,7 +729,7 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode) return 1; addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0); - if (!register_indirect_p (operand, mode, addr_mode)) + if (!m68hc11_valid_addressing_p (operand, mode, addr_mode)) return 0; if (TARGET_M6812 && GET_CODE (operand) == PLUS @@ -723,19 +777,19 @@ m68hc11_register_indirect_p (rtx operand, enum machine_mode mode) && reg_equiv_memory_loc[REGNO (operand)]) { operand = reg_equiv_memory_loc[REGNO (operand)]; - operand = eliminate_regs (operand, 0, NULL_RTX); + operand = eliminate_regs (operand, VOIDmode, NULL_RTX); } if (GET_CODE (operand) != MEM) return 0; operand = XEXP (operand, 0); addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); - return register_indirect_p (operand, mode, addr_mode); + return m68hc11_valid_addressing_p (operand, mode, addr_mode); } -static int -go_if_legitimate_address_internal (rtx operand, enum machine_mode mode, - int strict) +static bool +m68hc11_legitimate_address_p_1 (enum machine_mode mode, rtx operand, + bool strict) { int addr_mode; @@ -749,7 +803,7 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode, return 1; } addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0); - if (register_indirect_p (operand, mode, addr_mode)) + if (m68hc11_valid_addressing_p (operand, mode, addr_mode)) { return 1; } @@ -764,9 +818,9 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode, return 0; } -int -m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode, - int strict) +bool +m68hc11_legitimate_address_p (enum machine_mode mode, rtx operand, + bool strict) { int result; @@ -777,7 +831,7 @@ m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode, debug_rtx (operand); } - result = go_if_legitimate_address_internal (operand, mode, strict); + result = m68hc11_legitimate_address_p_1 (mode, operand, strict); if (debug_m6811) { @@ -797,14 +851,6 @@ m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode, return result; } -int -m68hc11_legitimize_address (rtx *operand ATTRIBUTE_UNUSED, - rtx old_operand ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return 0; -} - int m68hc11_reload_operands (rtx operands[]) @@ -830,7 +876,7 @@ m68hc11_reload_operands (rtx operands[]) } /* If the offset is out of range, we have to compute the address - with a separate add instruction. We try to do with with an 8-bit + with a separate add instruction. We try to do this with an 8-bit add on the A register. This is possible only if the lowest part of the offset (i.e., big_offset % 256) is a valid constant offset with respect to the mode. If it's not, we have to generate a @@ -930,7 +976,7 @@ m68hc11_emit_libcall (const char *name, enum rtx_code code, break; default: - abort (); + gcc_unreachable (); } insns = get_insns (); @@ -995,7 +1041,7 @@ m68hc11_indirect_p (rtx operand, enum machine_mode mode) operand = XEXP (operand, 0); addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); - return register_indirect_p (operand, mode, addr_mode); + return m68hc11_valid_addressing_p (operand, mode, addr_mode); } return 0; } @@ -1070,39 +1116,49 @@ symbolic_memory_operand (rtx op, enum machine_mode mode) jmp FNADDR */ -void -m68hc11_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt) +static void +m68hc11_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt) { const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM]; + rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); + rtx mem; /* 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)), + mem = adjust_address (m_tramp, HImode, 0); + emit_move_insn (mem, GEN_INT (0x18ce)); + mem = adjust_address (m_tramp, HImode, 2); + emit_move_insn (mem, cxt); + mem = adjust_address (m_tramp, HImode, 4); + emit_move_insn (mem, GEN_INT (0x18df)); + mem = adjust_address (m_tramp, QImode, 6); + emit_move_insn (mem, 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); + mem = adjust_address (m_tramp, QImode, 7); + emit_move_insn (mem, GEN_INT (0x7e)); + mem = adjust_address (m_tramp, HImode, 8); + emit_move_insn (mem, 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)), + mem = adjust_address (m_tramp, HImode, 0); + emit_move_insn (mem, GEN_INT (0x1803)); + mem = adjust_address (m_tramp, HImode, 2); + emit_move_insn (mem, cxt); + mem = adjust_address (m_tramp, HImode, 4); + emit_move_insn (mem, 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); + mem = adjust_address (m_tramp, QImode, 6); + emit_move_insn (mem, GEN_INT (0x06)); + mem = adjust_address (m_tramp, HImode, 7); + emit_move_insn (mem, fnaddr); } } @@ -1123,24 +1179,14 @@ m68hc11_handle_page0_attribute (tree *node, tree name, } else { - warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute ignored", + 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. */ @@ -1159,8 +1205,8 @@ m68hc11_handle_fntype_attribute (tree *node, tree name, && TREE_CODE (*node) != FIELD_DECL && TREE_CODE (*node) != TYPE_DECL) { - warning (0, "%qs attribute only applies to functions", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); *no_add_attrs = true; } @@ -1179,7 +1225,7 @@ m68hc11_encode_label (tree decl) { const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0); int len = strlen (str); - char *newstr = alloca (len + 2); + char *newstr = XALLOCAVEC (char, len + 2); newstr[0] = '@'; strcpy (&newstr[1], str); @@ -1244,13 +1290,14 @@ m68hc11_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED) trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE; if (trap_handler && is_far) { - warning (0, "% and % attributes are not compatible, ignoring %"); + warning (OPT_Wattributes, "% and % attributes are " + "not compatible, ignoring %"); trap_handler = 0; } if (trap_handler) { if (trap_handler_symbol != 0) - warning (0, "% attribute is already used"); + warning (OPT_Wattributes, "% attribute is already used"); else trap_handler_symbol = XEXP (rtl, 0); } @@ -1291,6 +1338,19 @@ m68hc11_is_trap_symbol (rtx sym) /* Argument support functions. */ +/* Given FROM and TO register numbers, say whether this elimination is + allowed. Frame pointer elimination is automatically handled. + + All other eliminations are valid. */ + +bool +m68hc11_can_eliminate (const int from, const int to) +{ + return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM + ? ! frame_pointer_needed + : true); +} + /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ int @@ -1342,7 +1402,7 @@ m68hc11_initial_elimination_offset (int from, int to) /* 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]) + if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) { size += 2; } @@ -1484,8 +1544,8 @@ m68hc11_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, `downward' to pad below, or `none' to inhibit padding. Structures are stored left shifted in their argument slot. */ -int -m68hc11_function_arg_padding (enum machine_mode mode, tree type) +enum direction +m68hc11_function_arg_padding (enum machine_mode mode, const_tree type) { if (type != 0 && AGGREGATE_TYPE_P (type)) return upward; @@ -1517,28 +1577,16 @@ emit_move_after_reload (rtx to, rtx from, rtx 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)); - } + add_reg_note (insn, REG_INC, XEXP (XEXP (to, 0), 0)); else if (IS_STACK_POP (from)) - { - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, - XEXP (XEXP (from, 0), 0), - REG_NOTES (insn)); - } + add_reg_note (insn, REG_INC, XEXP (XEXP (from, 0), 0)); /* 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)); - } + add_reg_note (insn, REG_INC, from); } int @@ -1556,7 +1604,7 @@ m68hc11_total_frame_size (void) size += HARD_REG_SIZE; for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++) - if (regs_ever_live[regno] && !call_used_regs[regno]) + if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) size += HARD_REG_SIZE; return size; @@ -1579,8 +1627,7 @@ expand_prologue (void) int regno; rtx scratch; - if (reload_completed != 1) - abort (); + gcc_assert (reload_completed == 1); size = get_frame_size (); @@ -1604,7 +1651,7 @@ expand_prologue (void) 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) + if (crtl->args.info.nregs == 2) scratch = iy_reg; else scratch = ix_reg; @@ -1669,7 +1716,7 @@ expand_prologue (void) /* 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]) + if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) { emit_move_after_reload (stack_push_word, gen_rtx_REG (HImode, regno), scratch); @@ -1685,20 +1732,19 @@ expand_epilogue (void) int return_size; rtx scratch; - if (reload_completed != 1) - abort (); + gcc_assert (reload_completed == 1); 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) + if (crtl->return_rtx == 0) return_size = 0; - else if (GET_CODE (current_function_return_rtx) == MEM) + else if (GET_CODE (crtl->return_rtx) == MEM) return_size = HARD_REG_SIZE; else - return_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx)); + return_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx)); if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE) scratch = iy_reg; @@ -1708,7 +1754,7 @@ expand_epilogue (void) /* 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]) + if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) { emit_move_after_reload (gen_rtx_REG (HImode, regno), stack_pop_word, scratch); @@ -1834,12 +1880,16 @@ m68hc11_gen_lowpart (enum machine_mode mode, rtx x) { 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 (); + switch (mode) + { + case SImode: + return GEN_INT (l[0]); + case HImode: + gcc_assert (GET_MODE (x) == SFmode); + return gen_int_mode (l[0], HImode); + default: + gcc_unreachable (); + } } if (mode == QImode && D_REG_P (x)) @@ -1848,12 +1898,15 @@ m68hc11_gen_lowpart (enum machine_mode mode, rtx x) /* 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 (); + switch (mode) + { + case SImode: + return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4); + case HImode: + return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2); + default: + gcc_unreachable (); + } } x = gen_lowpart (mode, x); @@ -1910,12 +1963,16 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x) 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 (); + switch (mode) + { + case SImode: + return GEN_INT (l[1]); + case HImode: + gcc_assert (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT); + return gen_int_mode ((l[0] >> 16), HImode); + default: + gcc_unreachable (); + } } if (GET_CODE (x) == CONST_INT) { @@ -1954,20 +2011,16 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x) } /* gen_highpart crashes when it is called with a SUBREG. */ - if (GET_CODE (x) == SUBREG) - { - return gen_rtx_SUBREG (mode, XEXP (x, 0), XEXP (x, 1)); - } - if (GET_CODE (x) == REG) + switch (GET_CODE (x)) { + case SUBREG: + return gen_rtx_SUBREG (mode, XEXP (x, 0), XINT (x, 1)); + case REG: if (REGNO (x) < FIRST_PSEUDO_REGISTER) return gen_rtx_REG (mode, REGNO (x)); else return gen_rtx_SUBREG (mode, x, 0); - } - - if (GET_CODE (x) == MEM) - { + case MEM: x = change_address (x, mode, 0); /* Return a different rtx to avoid to share it in several insns @@ -1976,8 +2029,10 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x) if (GET_CODE (x) == MEM) x = copy_rtx (x); return x; + + default: + gcc_unreachable (); } - abort (); } @@ -2109,8 +2164,8 @@ asm_print_register (FILE *file, int regno) 'T' generate the low-part temporary scratch register. The operand is ignored. */ -void -print_operand (FILE *file, rtx op, int letter) +static void +m68hc11_print_operand (FILE *file, rtx op, int letter) { if (letter == 't') { @@ -2178,56 +2233,36 @@ print_operand (FILE *file, rtx op, int letter) switch (GET_CODE (base)) { case PRE_DEC: - if (TARGET_M6812) - { - fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op))); - asm_print_register (file, REGNO (XEXP (base, 0))); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op))); + asm_print_register (file, REGNO (XEXP (base, 0))); break; case POST_DEC: - if (TARGET_M6812) - { - fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op))); - asm_print_register (file, REGNO (XEXP (base, 0))); - fprintf (file, "-"); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op))); + asm_print_register (file, REGNO (XEXP (base, 0))); + fprintf (file, "-"); break; case POST_INC: - if (TARGET_M6812) - { - fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op))); - asm_print_register (file, REGNO (XEXP (base, 0))); - fprintf (file, "+"); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op))); + asm_print_register (file, REGNO (XEXP (base, 0))); + fprintf (file, "+"); break; case PRE_INC: - if (TARGET_M6812) - { - fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op))); - asm_print_register (file, REGNO (XEXP (base, 0))); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op))); + asm_print_register (file, REGNO (XEXP (base, 0))); break; case MEM: - if (TARGET_M6812) - { - fprintf (file, "["); - print_operand_address (file, XEXP (base, 0)); - fprintf (file, "]"); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "["); + m68hc11_print_operand_address (file, XEXP (base, 0)); + fprintf (file, "]"); break; default: @@ -2322,8 +2357,8 @@ must_parenthesize (rtx op) assembler syntax for an instruction operand that is a memory reference whose address is ADDR. ADDR is an RTL expression. */ -void -print_operand_address (FILE *file, rtx addr) +static void +m68hc11_print_operand_address (FILE *file, rtx addr) { rtx base; rtx offset; @@ -2332,8 +2367,7 @@ print_operand_address (FILE *file, rtx addr) switch (GET_CODE (addr)) { case REG: - if (!REG_P (addr) || !REG_OK_FOR_BASE_STRICT_P (addr)) - abort (); + gcc_assert (REG_P (addr) && REG_OK_FOR_BASE_STRICT_P (addr)); fprintf (file, "0,"); asm_print_register (file, REGNO (addr)); @@ -2344,45 +2378,29 @@ print_operand_address (FILE *file, rtx addr) switch (GET_CODE (base)) { case PRE_DEC: - if (TARGET_M6812) - { - fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr))); - asm_print_register (file, REGNO (XEXP (base, 0))); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr))); + asm_print_register (file, REGNO (XEXP (base, 0))); break; case POST_DEC: - if (TARGET_M6812) - { - fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr))); - asm_print_register (file, REGNO (XEXP (base, 0))); - fprintf (file, "-"); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr))); + asm_print_register (file, REGNO (XEXP (base, 0))); + fprintf (file, "-"); break; case POST_INC: - if (TARGET_M6812) - { - fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr))); - asm_print_register (file, REGNO (XEXP (base, 0))); - fprintf (file, "+"); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr))); + asm_print_register (file, REGNO (XEXP (base, 0))); + fprintf (file, "+"); break; case PRE_INC: - if (TARGET_M6812) - { - fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr))); - asm_print_register (file, REGNO (XEXP (base, 0))); - } - else - abort (); + gcc_assert (TARGET_M6812); + fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr))); + asm_print_register (file, REGNO (XEXP (base, 0))); break; default: @@ -2405,10 +2423,11 @@ print_operand_address (FILE *file, rtx addr) base = XEXP (addr, 1); offset = XEXP (addr, 0); } - if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset))) + if (CONSTANT_ADDRESS_P (base)) { need_parenthesis = must_parenthesize (addr); + gcc_assert (CONSTANT_ADDRESS_P (offset)); if (need_parenthesis) fprintf (file, "("); @@ -2418,18 +2437,15 @@ print_operand_address (FILE *file, rtx addr) if (need_parenthesis) fprintf (file, ")"); } - else if (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base)) + else { + gcc_assert (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base)); if (REG_P (offset)) { - if (TARGET_M6812) - { - asm_print_register (file, REGNO (offset)); - fprintf (file, ","); - asm_print_register (file, REGNO (base)); - } - else - abort (); + gcc_assert (TARGET_M6812); + asm_print_register (file, REGNO (offset)); + fprintf (file, ","); + asm_print_register (file, REGNO (base)); } else { @@ -2444,10 +2460,6 @@ print_operand_address (FILE *file, rtx addr) asm_print_register (file, REGNO (base)); } } - else - { - abort (); - } break; default: @@ -2478,14 +2490,10 @@ m68hc11_expand_compare (enum rtx_code code, rtx op0, rtx op1) { rtx ret = 0; - if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) - abort (); - else - { - emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE (VOIDmode, op0, op1))); - ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); - } + gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) != MODE_FLOAT); + emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, + gen_rtx_COMPARE (VOIDmode, op0, op1))); + ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); return ret; } @@ -2613,7 +2621,7 @@ m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1, break; default: - abort (); + gcc_unreachable (); } /* @@ -2636,7 +2644,7 @@ m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1, } default: - abort (); + gcc_unreachable (); } return 0; } @@ -2922,7 +2930,7 @@ simplify_logical (enum machine_mode mode, int code, rtx operand, rtx *result) } static void -m68hc11_emit_logical (enum machine_mode mode, int code, rtx *operands) +m68hc11_emit_logical (enum machine_mode mode, enum rtx_code code, rtx *operands) { rtx result; int need_copy; @@ -2992,7 +3000,8 @@ m68hc11_emit_logical (enum machine_mode mode, int code, rtx *operands) } void -m68hc11_split_logical (enum machine_mode mode, int code, rtx *operands) +m68hc11_split_logical (enum machine_mode mode, enum rtx_code code, + rtx *operands) { rtx low[4]; rtx high[4]; @@ -3110,10 +3119,13 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) if (TARGET_M6812) { - if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1])) + rtx from = operands[1]; + rtx to = operands[0]; + + if (IS_STACK_PUSH (to) && H_REG_P (from)) { cc_status = cc_prev_status; - switch (REGNO (operands[1])) + switch (REGNO (from)) { case HARD_X_REGNUM: case HARD_Y_REGNUM: @@ -3124,14 +3136,14 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) output_asm_insn ("sts\t2,-sp", operands); break; default: - abort (); + gcc_unreachable (); } return; } - if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0])) + if (IS_STACK_POP (from) && H_REG_P (to)) { cc_status = cc_prev_status; - switch (REGNO (operands[0])) + switch (REGNO (to)) { case HARD_X_REGNUM: case HARD_Y_REGNUM: @@ -3139,7 +3151,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) output_asm_insn ("pul%0", operands); break; default: - abort (); + gcc_unreachable (); } return; } @@ -3162,11 +3174,52 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) else output_asm_insn ("st%1\t%0", operands); } + + /* The 68hc12 does not support (MEM:HI (MEM:HI)) with the movw + instruction. We have to use a scratch register as temporary location. + Trying to use a specific pattern or constrain failed. */ + else if (GET_CODE (to) == MEM && GET_CODE (XEXP (to, 0)) == MEM) + { + rtx ops[4]; + + ops[0] = to; + ops[2] = from; + ops[3] = 0; + if (dead_register_here (insn, d_reg)) + ops[1] = d_reg; + else if (dead_register_here (insn, ix_reg)) + ops[1] = ix_reg; + else if (dead_register_here (insn, iy_reg)) + ops[1] = iy_reg; + else + { + ops[1] = d_reg; + ops[3] = d_reg; + output_asm_insn ("psh%3", ops); + } + + ops[0] = to; + ops[2] = from; + output_asm_insn ("ld%1\t%2", ops); + output_asm_insn ("st%1\t%0", ops); + if (ops[3]) + output_asm_insn ("pul%3", ops); + } + + /* Use movw for non-null constants or when we are clearing + a volatile memory reference. However, this is possible + only if the memory reference has a small offset or is an + absolute address. */ + else if (GET_CODE (from) == CONST_INT + && INTVAL (from) == 0 + && (MEM_VOLATILE_P (to) == 0 + || m68hc11_small_indexed_indirect_p (to, HImode) == 0)) + { + output_asm_insn ("clr\t%h0", operands); + output_asm_insn ("clr\t%b0", operands); + } else { - rtx from = operands[1]; - rtx to = operands[0]; - if ((m68hc11_register_indirect_p (from, GET_MODE (from)) && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from))) || (m68hc11_register_indirect_p (to, GET_MODE (to)) @@ -3183,6 +3236,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) ops[0] = to; ops[1] = operands[2]; m68hc11_gen_movhi (insn, ops); + return; } else { @@ -3190,19 +3244,11 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) fatal_insn ("move insn not handled", insn); } } - else - { - if (GET_CODE (from) == CONST_INT && INTVAL (from) == 0) - { - output_asm_insn ("clr\t%h0", operands); - output_asm_insn ("clr\t%b0", operands); - } - else - { - m68hc11_notice_keep_cc (operands[0]); - output_asm_insn ("movw\t%1,%0", operands); - } - } + else + { + m68hc11_notice_keep_cc (operands[0]); + output_asm_insn ("movw\t%1,%0", operands); + } } return; } @@ -3221,7 +3267,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) output_asm_insn ("pulb", operands); break; default: - abort (); + gcc_unreachable (); } return; } @@ -3445,7 +3491,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) output_asm_insn ("psha", operands); break; default: - abort (); + gcc_unreachable (); } return; } @@ -3530,8 +3576,10 @@ m68hc11_gen_movqi (rtx insn, rtx *operands) } else if (H_REG_P (operands[0])) { - if (Q_REG_P (operands[0])) - output_asm_insn ("lda%0\t%b1", operands); + if (IS_STACK_POP (operands[1])) + output_asm_insn ("pul%b0", operands); + else if (Q_REG_P (operands[0])) + output_asm_insn ("lda%0\t%b1", operands); else if (D_REG_P (operands[0])) output_asm_insn ("ldab\t%b1", operands); else @@ -3892,7 +3940,11 @@ m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) { cc_status.flags = 0; cc_status.value1 = XEXP (exp, 0); - cc_status.value2 = XEXP (exp, 1); + if (GET_CODE (XEXP (exp, 1)) == COMPARE + && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0)))) + cc_status.value2 = XEXP (XEXP (exp, 1), 0); + else + cc_status.value2 = XEXP (exp, 1); } else { @@ -4254,9 +4306,7 @@ m68hc11_check_z_replacement (rtx insn, struct replace_info *info) info->must_restore_reg = 0; info->found_call = 1; info->can_use_d = 0; - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; + SET_INSN_DELETED (insn); info->last = NEXT_INSN (insn); return 0; } @@ -4337,9 +4387,7 @@ m68hc11_check_z_replacement (rtx insn, struct replace_info *info) info->must_restore_reg = 0; info->found_call = 1; info->can_use_d = 0; - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; + SET_INSN_DELETED (insn); info->last = NEXT_INSN (insn); return 0; } @@ -5015,7 +5063,7 @@ static void m68hc11_reorg (void) { int split_done = 0; - rtx insn, first; + rtx first; z_replacement_completed = 0; z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM); @@ -5025,7 +5073,7 @@ m68hc11_reorg (void) replacement, unshare everything. */ unshare_all_rtl_again (first); - /* Force a split of all splitable insn. This is necessary for the + /* Force a split of all splittable insn. This is necessary for the Z register replacement mechanism because we end up with basic insns. */ split_all_insns_noflow (); split_done = 1; @@ -5047,29 +5095,9 @@ m68hc11_reorg (void) description to use the best assembly directives. */ if (optimize) { - /* Before recomputing the REG_DEAD notes, remove all of them. - This is necessary because the reload_cse_regs() pass can - have replaced some (MEM) with a register. In that case, - the REG_DEAD that could exist for that register may become - wrong. */ - for (insn = first; insn; insn = NEXT_INSN (insn)) - { - if (INSN_P (insn)) - { - rtx *pnote; - - pnote = ®_NOTES (insn); - while (*pnote != 0) - { - if (REG_NOTE_KIND (*pnote) == REG_DEAD) - *pnote = XEXP (*pnote, 1); - else - pnote = &XEXP (*pnote, 1); - } - } - } - - life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES); + df_note_add_problem (); + df_analyze (); + df_remove_problem (df_note); } z_replacement_completed = 2; @@ -5105,9 +5133,7 @@ m68hc11_reorg (void) if (GET_CODE (body) == SET && rtx_equal_p (SET_SRC (body), SET_DEST (body))) { - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; + SET_INSN_DELETED (insn); continue; } } @@ -5130,10 +5156,10 @@ m68hc11_init_libfuncs (void) /* Cost of moving memory. */ int -m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class class, +m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class rclass, int in ATTRIBUTE_UNUSED) { - if (class <= H_REGS && class > NO_REGS) + if (rclass <= H_REGS && rclass > NO_REGS) { if (GET_MODE_SIZE (mode) <= 2) return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress); @@ -5178,7 +5204,7 @@ m68hc11_register_move_cost (enum machine_mode mode, enum reg_class from, If ADDR is not a valid address, its cost is irrelevant. */ static int -m68hc11_address_cost (rtx addr) +m68hc11_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED) { int cost = 4; @@ -5263,7 +5289,7 @@ m68hc11_shift_cost (enum machine_mode mode, rtx x, int shift) { int total; - total = rtx_cost (x, SET); + total = rtx_cost (x, SET, !optimize_size); if (mode == QImode) total += m68hc11_cost->shiftQI_const[shift % 8]; else if (mode == HImode) @@ -5307,14 +5333,14 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1))); } - total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code); + total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size); total += m68hc11_cost->shift_var; return total; case AND: case XOR: case IOR: - total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code); + total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size); total += m68hc11_cost->logical; /* Logical instructions are byte instructions only. */ @@ -5323,7 +5349,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, case MINUS: case PLUS: - total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code); + total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size); total += m68hc11_cost->add; if (GET_MODE_SIZE (mode) > 2) { @@ -5334,7 +5360,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, case UDIV: case DIV: case MOD: - total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code); + total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size); switch (mode) { case QImode: @@ -5357,18 +5383,19 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, if (mode == HImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND) return m68hc11_cost->multQI - + rtx_cost (XEXP (XEXP (x, 0), 0), code) - + rtx_cost (XEXP (XEXP (x, 1), 0), code); + + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size) + + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size); /* emul instruction produces 32-bit result for 68HC12. */ if (TARGET_M6812 && mode == SImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND) return m68hc11_cost->multHI - + rtx_cost (XEXP (XEXP (x, 0), 0), code) - + rtx_cost (XEXP (XEXP (x, 1), 0), code); + + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size) + + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size); - total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code); + total = rtx_cost (XEXP (x, 0), code, !optimize_size) + + rtx_cost (XEXP (x, 1), code, !optimize_size); switch (mode) { case QImode: @@ -5395,7 +5422,8 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, case COMPARE: case ABS: case ZERO_EXTEND: - total = extra_cost + rtx_cost (XEXP (x, 0), code); + case ZERO_EXTRACT: + total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size); if (mode == QImode) { return total + COSTS_N_INSNS (1); @@ -5422,8 +5450,12 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, } static bool -m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total) +m68hc11_rtx_costs (rtx x, int codearg, int outer_code_arg, int *total, + bool speed ATTRIBUTE_UNUSED) { + enum rtx_code code = (enum rtx_code) codearg; + enum rtx_code outer_code = (enum rtx_code) outer_code_arg; + switch (code) { /* Constants are cheap. Moving them in registers must be avoided @@ -5444,6 +5476,10 @@ m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total) *total = 0; return true; + case ZERO_EXTRACT: + if (outer_code != COMPARE) + return false; + case ROTATE: case ROTATERT: case ASHIFT: @@ -5516,7 +5552,7 @@ m68hc11_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, in the register (D + X = 4). */ static bool -m68hc11_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) +m68hc11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) { if (TYPE_MODE (type) == BLKmode) {