This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Fix move and add code generation for 68HC12
- To: gcc-patches at gcc dot gnu dot org
- Subject: [PATCH]: Fix move and add code generation for 68HC12
- From: Stephane Carrez <Stephane dot Carrez at worldnet dot fr>
- Date: Sun, 04 Mar 2001 12:54:25 +0100
Hi!
I've committed the patch below in 3.0 to fix the following problems
in 68HC12 code generation:
- The movsi/movdi split was generating incorrect moves for
a push when the source operand is indexed by the stack
(sp is changed while values are pushed).
- The HC12 move code was incorrect for byte operations to/from
index registers.
- Fix HC12 addhi3.
Stephane
2001-03-04 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* config/m68hc11/m68hc11.md (*addhi3_68hc12): Fix generation
and use m68hc11_notice_keep_cc when using leax/leay.
(addhi3 split): Reject split if the insn is handled by
leax/leay above.
* config/m68hc11/m68hc11.c (m68hc11_split_move): For 68HC12 the
push must be handled in a special way if the source operand uses
sp as index register.
(m68hc11_notice_keep_cc): New function.
(m68hc11_gen_movhi): Use it when an insn changes a register but
not the flags.
(m68hc11_gen_movqi): Fix move for 68HC12.
* config/m68hc11/m68hc11-protos.h (m68hc11_notice_keep_cc): Declare.
Index: config/m68hc11/m68hc11-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m68hc11/m68hc11-protos.h,v
retrieving revision 1.1
diff -u -p -r1.1 m68hc11-protos.h
--- m68hc11-protos.h 2000/09/08 20:54:44 1.1
+++ m68hc11-protos.h 2001/03/04 12:45:58
@@ -73,6 +73,7 @@ extern int m68hc11_go_if_legitimate_addr
extern int m68hc11_legitimize_address PARAMS((rtx*, rtx, enum machine_mode));
extern void m68hc11_notice_update_cc PARAMS((rtx, rtx));
+extern void m68hc11_notice_keep_cc PARAMS((rtx));
extern void m68hc11_reorg PARAMS((rtx));
Index: config/m68hc11/m68hc11.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m68hc11/m68hc11.c,v
retrieving revision 1.2.2.1
diff -u -p -r1.2.2.1 m68hc11.c
--- m68hc11.c 2001/03/04 10:47:53 1.2.2.1
+++ m68hc11.c 2001/03/04 12:46:17
@@ -2527,6 +2527,7 @@ m68hc11_split_move (to, from, scratch)
rtx low_to, low_from;
rtx high_to, high_from;
enum machine_mode mode;
+ int offset = 0;
mode = GET_MODE (to);
if (GET_MODE_SIZE (mode) == 8)
@@ -2536,6 +2537,22 @@ m68hc11_split_move (to, from, scratch)
else
mode = QImode;
+ if (TARGET_M6812
+ && IS_STACK_PUSH (to)
+ && reg_mentioned_p (gen_rtx (REG, HImode, HARD_SP_REGNUM), from))
+ {
+ if (mode == SImode)
+ {
+ offset = 4;
+ }
+ else if (mode == HImode)
+ {
+ offset = 2;
+ }
+ else
+ offset = 0;
+ }
+
low_to = m68hc11_gen_lowpart (mode, to);
high_to = m68hc11_gen_highpart (mode, to);
@@ -2550,6 +2567,11 @@ m68hc11_split_move (to, from, scratch)
else
high_from = m68hc11_gen_highpart (mode, from);
+ if (offset)
+ {
+ high_from = adj_offsettable_operand (high_from, offset);
+ low_from = high_from;
+ }
if (mode == SImode)
{
m68hc11_split_move (low_to, low_from, scratch);
@@ -2842,6 +2864,7 @@ m68hc11_gen_movhi (insn, operands)
{
if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[1]))
{
case HARD_X_REGNUM:
@@ -2856,6 +2879,7 @@ m68hc11_gen_movhi (insn, operands)
}
if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[0]))
{
case HARD_X_REGNUM:
@@ -2870,6 +2894,7 @@ m68hc11_gen_movhi (insn, operands)
}
if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
{
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("tfr\t%1,%0", operands);
}
else if (H_REG_P (operands[0]))
@@ -2911,6 +2936,7 @@ m68hc11_gen_movhi (insn, operands)
else
{
/* !!!! SCz wrong here. */
+ fatal_insn ("Move insn not handled", insn);
}
}
else
@@ -2922,6 +2948,7 @@ m68hc11_gen_movhi (insn, operands)
}
else
{
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("movw\t%1,%0", operands);
}
}
@@ -2931,6 +2958,7 @@ m68hc11_gen_movhi (insn, operands)
if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[0]))
{
case HARD_X_REGNUM:
@@ -2966,7 +2994,7 @@ m68hc11_gen_movhi (insn, operands)
}
else
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("pshx\n\tpula\n\tpulb", operands);
}
}
@@ -3021,7 +3049,7 @@ m68hc11_gen_movhi (insn, operands)
}
else
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("pshb", operands);
output_asm_insn ("psha", operands);
output_asm_insn ("pulx", operands);
@@ -3077,7 +3105,7 @@ m68hc11_gen_movhi (insn, operands)
case HARD_SP_REGNUM:
if (D_REG_P (operands[1]))
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("xgdx", operands);
output_asm_insn ("txs", operands);
output_asm_insn ("xgdx", operands);
@@ -3118,6 +3146,7 @@ m68hc11_gen_movhi (insn, operands)
if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[1]))
{
case HARD_X_REGNUM:
@@ -3201,25 +3230,26 @@ m68hc11_gen_movqi (insn, operands)
if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
{
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("tfr\t%1,%0", operands);
}
else if (H_REG_P (operands[0]))
{
if (Q_REG_P (operands[0]))
- output_asm_insn ("lda%0\t%1", operands);
+ output_asm_insn ("lda%0\t%b1", operands);
else if (D_REG_P (operands[0]))
- output_asm_insn ("ldab\t%1", operands);
+ output_asm_insn ("ldab\t%b1", operands);
else
- output_asm_insn ("ld%0\t%1", operands);
+ goto m6811_move;
}
else if (H_REG_P (operands[1]))
{
if (Q_REG_P (operands[1]))
- output_asm_insn ("sta%1\t%0", operands);
+ output_asm_insn ("sta%1\t%b0", operands);
else if (D_REG_P (operands[1]))
- output_asm_insn ("staa\t%0", operands);
+ output_asm_insn ("stab\t%b0", operands);
else
- output_asm_insn ("st%1\t%0", operands);
+ goto m6811_move;
}
else
{
@@ -3246,6 +3276,7 @@ m68hc11_gen_movqi (insn, operands)
else
{
/* !!!! SCz wrong here. */
+ fatal_insn ("Move insn not handled", insn);
}
}
else
@@ -3256,13 +3287,15 @@ m68hc11_gen_movqi (insn, operands)
}
else
{
- output_asm_insn ("movb\t%1,%0", operands);
+ m68hc11_notice_keep_cc (operands[0]);
+ output_asm_insn ("movb\t%b1,%b0", operands);
}
}
}
return;
}
+ m6811_move:
if (H_REG_P (operands[0]))
{
switch (REGNO (operands[0]))
@@ -3637,6 +3670,24 @@ m68hc11_notice_update_cc (exp, insn)
&& reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
cc_status.value2 = 0;
}
+
+/* The current instruction does not affect the flags but changes
+ the register 'reg'. See if the previous flags can be kept for the
+ next instruction to avoid a comparison. */
+void
+m68hc11_notice_keep_cc (reg)
+ rtx reg;
+{
+ if (reg == 0
+ || cc_prev_status.value1 == 0
+ || rtx_equal_p (reg, cc_prev_status.value1)
+ || (cc_prev_status.value2
+ && reg_mentioned_p (reg, cc_prev_status.value2)))
+ CC_STATUS_INIT;
+ else
+ cc_status = cc_prev_status;
+}
+
/* Machine Specific Reorg. */
Index: config/m68hc11/m68hc11.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m68hc11/m68hc11.md,v
retrieving revision 1.3.4.2
diff -u -p -r1.3.4.2 m68hc11.md
--- m68hc11.md 2001/03/04 10:27:07 1.3.4.2
+++ m68hc11.md 2001/03/04 12:46:29
@@ -1760,25 +1760,39 @@
"")
(define_insn "*addhi3_68hc12"
- [(set (match_operand:HI 0 "register_operand" "=d,A*w,A*w")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw")
- (match_operand:HI 2 "general_operand" "imA*wu,id,id")))]
+ [(set (match_operand:HI 0 "register_operand" "=*d,A*w,A*w,A")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw,0")
+ (match_operand:HI 2 "general_operand" "imA*wu,id,id,!muA")))]
"TARGET_M6812"
"*
{
int val;
const char* insn_code;
+ if (which_alternative >= 3)
+ {
+ if (A_REG_P (operands[2]))
+ {
+ CC_STATUS_INIT;
+ output_asm_insn (\"xgd%2\", operands);
+ output_asm_insn (\"lea%0 d,%0\", operands);
+ return \"xgd%2\";
+ }
+ return \"#\";
+ }
+
if (D_REG_P (operands[0]))
{
if (X_REG_P (operands[2]))
{
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn (\"xgdx\", operands);
output_asm_insn (\"leax\\td,%2\", operands);
return \"xgdx\";
}
else if (Y_REG_P (operands[2]))
{
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn (\"xgdy\", operands);
output_asm_insn (\"leay\\td,%2\", operands);
return \"xgdy\";
@@ -1798,7 +1812,7 @@
if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
switch (REGNO (operands[0]))
{
case HARD_X_REGNUM:
@@ -3191,7 +3205,9 @@
/* If we are adding a small constant to X or Y, it's
better to use one or several inx/iny instructions. */
&& !(GET_CODE (operands[3]) == PLUS
- && (TARGET_M6812
+ && ((TARGET_M6812
+ && (immediate_operand (operands[2], HImode)
+ || hard_reg_operand (operands[2], HImode)))
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >= -4
&& INTVAL (operands[2]) <= 4)))"
@@ -3238,7 +3254,9 @@
/* If we are adding a small constant to X or Y, it's
better to use one or several inx/iny instructions. */
&& !(GET_CODE (operands[3]) == PLUS
- && (TARGET_M6812
+ && ((TARGET_M6812
+ && (immediate_operand (operands[2], HImode)
+ || hard_reg_operand (operands[2], HImode)))
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >= -4
&& INTVAL (operands[2]) <= 4)))"