aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/m68hc11/m68hc11.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/m68hc11/m68hc11.c')
-rw-r--r--gcc/config/m68hc11/m68hc11.c150
1 files changed, 90 insertions, 60 deletions
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index ce057a387b3..383025d4ae1 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -1,5 +1,5 @@
/* Subroutines for code generation on Motorola 68HC11 and 68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
@@ -1027,6 +1027,7 @@ reg_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;
@@ -1034,10 +1035,20 @@ reg_or_some_mem_operand (rtx operand, enum machine_mode mode)
if (IS_STACK_PUSH (operand))
return 1;
- if (m68hc11_register_indirect_p (operand, mode))
- 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;
- 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);
@@ -2044,6 +2055,10 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x)
{
return gen_int_mode (val >> 16, HImode);
}
+ else if (mode == SImode)
+ {
+ return gen_int_mode (val >> 32, SImode);
+ }
}
if (mode == QImode && D_REG_P (x))
return gen_rtx (REG, mode, HARD_A_REGNUM);
@@ -2926,15 +2941,7 @@ m68hc11_split_move (rtx to, rtx from, rtx scratch)
high_to = m68hc11_gen_highpart (mode, to);
low_from = m68hc11_gen_lowpart (mode, from);
- if (mode == SImode && GET_CODE (from) == CONST_INT)
- {
- if (INTVAL (from) >= 0)
- high_from = const0_rtx;
- else
- high_from = constm1_rtx;
- }
- else
- high_from = m68hc11_gen_highpart (mode, from);
+ high_from = m68hc11_gen_highpart (mode, from);
if (offset)
{
@@ -3117,26 +3124,8 @@ m68hc11_split_logical (enum machine_mode mode, int code, rtx *operands)
low[2] = m68hc11_gen_lowpart (mode, operands[2]);
high[0] = m68hc11_gen_highpart (mode, operands[0]);
-
- if (mode == SImode && GET_CODE (operands[1]) == CONST_INT)
- {
- if (INTVAL (operands[1]) >= 0)
- high[1] = const0_rtx;
- else
- high[1] = constm1_rtx;
- }
- else
- high[1] = m68hc11_gen_highpart (mode, operands[1]);
-
- if (mode == SImode && GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) >= 0)
- high[2] = const0_rtx;
- else
- high[2] = constm1_rtx;
- }
- else
- high[2] = m68hc11_gen_highpart (mode, operands[2]);
+ high[1] = m68hc11_gen_highpart (mode, operands[1]);
+ high[2] = m68hc11_gen_highpart (mode, operands[2]);
low[3] = operands[3];
high[3] = operands[3];
@@ -3243,10 +3232,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:
@@ -3261,10 +3253,10 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
}
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:
@@ -3295,11 +3287,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))
@@ -3316,6 +3349,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
ops[0] = to;
ops[1] = operands[2];
m68hc11_gen_movhi (insn, ops);
+ return;
}
else
{
@@ -3323,19 +3357,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;
}
@@ -3663,8 +3689,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
@@ -5028,9 +5056,11 @@ m68hc11_z_replacement (rtx insn)
if (info.save_before_last)
save_pos_insn = PREV_INSN (save_pos_insn);
- emit_insn_before (gen_movhi (gen_rtx (REG, HImode, SOFT_Z_REGNUM),
- gen_rtx (REG, HImode, info.regno)),
- save_pos_insn);
+ /* Use emit_insn_after () to ensure the new insn is part of
+ the good basic block. */
+ emit_insn_after (gen_movhi (gen_rtx (REG, HImode, SOFT_Z_REGNUM),
+ gen_rtx (REG, HImode, info.regno)),
+ PREV_INSN (save_pos_insn));
}
if (info.must_push_reg && info.last)
@@ -5069,8 +5099,8 @@ m68hc11_z_replacement (rtx insn)
else
dst = gen_rtx (REG, HImode, SOFT_SAVED_XY_REGNUM);
- emit_insn_before (gen_movhi (gen_rtx (REG, HImode, info.regno),
- dst), insn);
+ emit_insn_after (gen_movhi (gen_rtx (REG, HImode, info.regno),
+ dst), PREV_INSN (insn));
}
}