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)
{