This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH]: Fix move and add code generation for 68HC12


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]