if (GET_CODE (operand) == MEM)
{
rtx op = XEXP (operand, 0);
+ int addr_mode;
if (symbolic_memory_operand (op, mode))
return 1;
if (IS_STACK_PUSH (operand))
return 1;
- if (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);
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:
}
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:
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))
ops[0] = to;
ops[1] = operands[2];
m68hc11_gen_movhi (insn, ops);
+ return;
}
else
{
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;
}
}
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
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)
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));
}
}