+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (emit_move_after_reload): Add a REG_INC
+ note on the insn that sets the soft frame register.
+ (must_parenthesize): ix and iy are also reserved names.
+ (print_operand_address): One more place where parenthesis are required
+ to avoid confusion with register names.
+ (m68hc11_gen_movhi): Allow push of stack pointer.
+ (m68hc11_check_z_replacement): Fix handling of parallel with a
+ clobber.
+ (m68hc11_z_replacement): Must update the REG_INC notes to tell what
+ the replacement register is.
+ * config/m68hc11/m68hc11.h (REG_CLASS_CONTENTS): Switch Z_REGS
+ and D8_REGS classes.
+ (MODES_TIEABLE_P): All modes are tieable except QImode.
+
2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* config/m68hc11/larith.asm (___adddi3): Optimize saving of result.
XEXP (XEXP (from, 0), 0),
REG_NOTES (insn));
}
+
+ /* 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));
+ }
}
int
|| strcasecmp (name, "d") == 0
|| strcasecmp (name, "x") == 0
|| strcasecmp (name, "y") == 0
+ || strcasecmp (name, "ix") == 0
+ || strcasecmp (name, "iy") == 0
|| strcasecmp (name, "pc") == 0
|| strcasecmp (name, "sp") == 0
|| strcasecmp (name, "ccr") == 0) ? 1 : 0;
}
else
{
+ need_parenthesis = must_parenthesize (offset);
+ if (need_parenthesis)
+ asm_fprintf (file, "(");
+
output_addr_const (file, offset);
+ if (need_parenthesis)
+ asm_fprintf (file, ")");
asm_fprintf (file, ",");
asm_print_register (file, REGNO (base));
}
case HARD_D_REGNUM:
output_asm_insn ("psh%1", operands);
break;
+ case HARD_SP_REGNUM:
+ output_asm_insn ("sts\t-2,sp", operands);
+ break;
default:
abort ();
}
info->must_save_reg = 0;
info->must_restore_reg = 0;
}
- info->last = NEXT_INSN (insn);
+ if (info->first != insn
+ && ((info->y_used && ix_clobber)
+ || (info->x_used && iy_clobber)))
+ info->last = insn;
+ else
+ info->last = NEXT_INSN (insn);
info->save_before_last = 1;
}
return 0;
if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
|| GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
{
+ rtx note;
+
if (debug_m6811 && reg_mentioned_p (replace_reg, body))
{
printf ("Reg mentioned here...:\n");
replace_reg_qi = gen_rtx (REG, QImode, REGNO (replace_reg));
validate_replace_rtx (z_reg_qi, replace_reg_qi, insn);
}
+
+ /* If there is a REG_INC note on Z, replace it with a
+ REG_INC note on the replacement register. This is necessary
+ to make sure that the flow pass will identify the change
+ and it will not remove a possible insn that saves Z. */
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ {
+ if (REG_NOTE_KIND (note) == REG_INC
+ && GET_CODE (XEXP (note, 0)) == REG
+ && REGNO (XEXP (note, 0)) == REGNO (z_reg))
+ {
+ XEXP (note, 0) = replace_reg;
+ }
+ }
}
if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
break;
/* Value is 1 if it is a good idea to tie two pseudo registers when one has
mode MODE1 and one has mode MODE2. If HARD_REGNO_MODE_OK could produce
different values for MODE1 and MODE2, for any hard reg, then this must be
- 0 for correct output. */
+ 0 for correct output.
+
+ All modes are tieable except QImode. */
#define MODES_TIEABLE_P(MODE1, MODE2) \
(((MODE1) == (MODE2)) \
- || ((MODE1) == SImode && (MODE2) == HImode) \
- || ((MODE1) == HImode && (MODE2) == SImode))
+ || ((MODE1) != QImode && (MODE2) != QImode))
\f
/* Define the classes of registers for register constraints in the
/* SP_REGS */ { 0x00000008, 0x00000000 }, /* SP */ \
/* DA_REGS */ { 0x00000020, 0x00000000 }, /* A */ \
/* DB_REGS */ { 0x00000040, 0x00000000 }, /* B */ \
-/* D8_REGS */ { 0x00000060, 0x00000000 }, /* A B */ \
/* Z_REGS */ { 0x00000100, 0x00000000 }, /* Z */ \
+/* D8_REGS */ { 0x00000060, 0x00000000 }, /* A B */ \
/* Q_REGS */ { 0x00000062, 0x00000000 }, /* A B D */ \
/* D_OR_X_REGS */ { 0x00000003, 0x00000000 }, /* D X */ \
/* D_OR_Y_REGS */ { 0x00000006, 0x00000000 }, /* D Y */ \