m68hc11-protos.h (ix_reg): Declare.
authorStephane Carrez <Stephane.Carrez@worldnet.fr>
Sat, 16 Mar 2002 12:52:20 +0000 (13:52 +0100)
committerStephane Carrez <ciceron@gcc.gnu.org>
Sat, 16 Mar 2002 12:52:20 +0000 (13:52 +0100)
* config/m68hc11/m68hc11-protos.h (ix_reg): Declare.
* config/m68hc11/m68hc11.md ("addsi3"): Use general_operand for sources.
(splits): Remove unused add splits.
("*addhi3_68hc12"): Tune constraints.
("addhi_sp"): Try to use X instead of Y in all cases and if the
constant fits in 8-bits and D is dead use abx/aby instructions.
("*addhi3"): Remove extern declaration of ix_reg.
("*subsi3"): Optimize and provide new split.
("subhi3"): Cleanup.
("*subhi3_sp"): Avoid saving X if we know it is dead.
(arith splits): For 68hc12 save the address register on the stack
and do the arithmetic operation with a pop.

From-SVN: r50880

gcc/ChangeLog
gcc/config/m68hc11/m68hc11-protos.h
gcc/config/m68hc11/m68hc11.md

index ba8d64a..87181f2 100644 (file)
@@ -1,5 +1,20 @@
 2002-03-16  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
 
+       * config/m68hc11/m68hc11-protos.h (ix_reg): Declare.
+       * config/m68hc11/m68hc11.md ("addsi3"): Use general_operand for sources.
+       (splits): Remove unused add splits.
+       ("*addhi3_68hc12"): Tune constraints.
+       ("addhi_sp"): Try to use X instead of Y in all cases and if the
+       constant fits in 8-bits and D is dead use abx/aby instructions.
+       ("*addhi3"): Remove extern declaration of ix_reg.
+       ("*subsi3"): Optimize and provide new split.
+       ("subhi3"): Cleanup.
+       ("*subhi3_sp"): Avoid saving X if we know it is dead.
+       (arith splits): For 68hc12 save the address register on the stack
+       and do the arithmetic operation with a pop.
+
+2002-03-16  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
        * config/m68hc11/m68hc11.md ("*movqi_68hc12"): Fix constraints, avoid
        allocating QImode in address registers.
        ("*movqi_m68hc11"): Likewise.
index 27358b7..3611485 100644 (file)
@@ -49,6 +49,7 @@ extern rtx m68hc11_compare_op0;
 extern rtx m68hc11_compare_op1;
 extern rtx m68hc11_soft_tmp_reg;
 extern rtx iy_reg;
+extern rtx ix_reg;
 extern rtx d_reg;
 
 extern void m68hc11_initialize_trampoline PARAMS((rtx, rtx, rtx));
index df82cd4..092b903 100644 (file)
   ""
   "*
 {
-  extern rtx ix_reg;
   rtx ops[3];
   int need_tst = 0;
 
   ""
   "*
 {
-  extern rtx ix_reg;
   rtx ops[2];
   int x_reg_used;
 
 ;;
 (define_expand "addsi3"
   [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                    (plus:SI (match_operand:SI 1 "register_operand" "")
+                    (plus:SI (match_operand:SI 1 "general_operand" "")
                              (match_operand:SI 2 "general_operand" "")))
               (clobber (match_scratch:HI 3 ""))])]
   ""
   "")
 
-;;
-;; Translate D = D + D into D = D << 1
-;; We have to do this because adding a register to itself is not possible.
-;;
-;; Manipulation of A and B registers directly confuses the cse-regs pass
-;; so the split must be made after z-replacement register.
-;;
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
-                (match_dup 0)))
-   (clobber (match_scratch:HI 1 "=X"))]
-  "reload_completed && z_replacement_completed == 2"
-  [(set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
-   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
-              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
-   (set (reg:QI B_REGNUM) (rotate:QI (reg:QI B_REGNUM) (reg:QI CC_REGNUM)))
-   (set (reg:QI A_REGNUM) (rotate:QI (reg:QI A_REGNUM) (reg:QI CC_REGNUM)))
-   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
-              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
-  "")
-
-
 (define_insn "*addsi3_zero_extendhi"
   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
        (plus:SI (zero_extend:SI 
     }
 }")
 
-(define_split /* "*addhi3_strict_low_part" */
-  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+dxy"))
-        (plus:QI (match_operand:QI 1 "register_operand" "")
-                 (match_operand:QI 2 "general_operand" "")))]
-  "0 && z_replacement_completed == 2"
-  [(set (match_dup 0)
-       (plus:QI (match_dup 1) (match_dup 2)))]
-  "")
-
-(define_split /* "*addhi3_strict_low_part" */
-  [(set (match_operand:HI 0 "register_operand" "=dA")
-        (plus:HI (match_operand:HI 1 "register_operand" "%0")
-                 (match_operand:HI 2 "general_operand" "")))
-   (clobber (match_scratch:HI 3 ""))]
-  "0 && z_replacement_completed == 2 && !SP_REG_P (operands[0])"
-  [(set (match_dup 0)
-       (plus:HI (match_dup 1) (match_dup 2)))]
-  "")
-
 (define_insn "*addhi3_68hc12"
-  [(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")))]
+  [(set (match_operand:HI 0 "register_operand" "=xy,d,xy*z*w,xy*z*w,xy*z")
+        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*zw,0")
+                 (match_operand:HI 2 "general_operand" "N,im*A*wu,id,id,!mu*A")))]
   "TARGET_M6812"
   "*
 {
   int val;
   const char* insn_code;
 
-  if (which_alternative >= 3)
+  if (which_alternative >= 4)
     {
       if (A_REG_P (operands[2]))
         {
   else
     val = 1000;
 
-  if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
+  if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
     {
       m68hc11_notice_keep_cc (operands[0]);
       switch (REGNO (operands[0]))
 {
   HOST_WIDE_INT val;
 
+  if (optimize && Y_REG_P (operands[3])
+      && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM)))
+    operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+
   if (GET_CODE (operands[2]) == CONST_INT
       && (val = INTVAL (operands[2])) != 0
       && (CONST_OK_FOR_LETTER_P (val, 'P')
          || (val > 0 && val <= 8)))
     {
-      if (optimize && Y_REG_P (operands[3])
-          && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM)))
-       operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM);
       while (val > 1 || val < -1)
        {
          if (val > 0)
       return \"\";
     }
 
-  /* Need to transfer to SP to IY and then to D register.
-     Register IY is lost, this is specified by the (clobber) statement.  */
+  /* Need to transfer to SP to X/Y and then to D register.
+     Register X/Y is lost, this is specified by the (clobber) statement.  */
   output_asm_insn (\"ts%3\", operands);
-  output_asm_insn (\"xgd%3\", operands);
-  output_asm_insn (\"addd\\t%2\", operands);
-  output_asm_insn (\"xgd%3\", operands);
+  if (GET_CODE (operands[2]) == CONST_INT
+      && ((val = INTVAL (operands[2]) >= 0 && val < 0x100))
+      && dead_register_here (insn, gen_rtx (REG, HImode, HARD_D_REGNUM)))
+    {
+      output_asm_insn (\"ldab\\t%2\", operands);
+      output_asm_insn (\"ab%3\", operands);
+      CC_STATUS_INIT;
+    }
+  else
+    {
+      output_asm_insn (\"xgd%3\", operands);
+      output_asm_insn (\"addd\\t%2\", operands);
+      output_asm_insn (\"xgd%3\", operands);
+    }
 
    /* The status flags correspond to the addd.  xgdy and tys do not
       modify the flags.  */
   return \"t%3s\";
 }")
 
-;;
-;; Translate d = d + d into d = d << 1
-;; We have to do this because adding a register to itself is not possible.
-;; ??? It's not clear whether this is really necessary.
-;;
-(define_split
-  [(set (match_operand:HI 0 "hard_reg_operand" "=dA")
-       (plus:HI (match_dup 0)
-                (match_dup 0)))]
-  "reload_completed"
-  [(set (match_dup 0) (ashift:HI (match_dup 0) (const_int 1)))]
-  "")
-
 (define_insn "*addhi3"
   [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d*A")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0")
 {
   const char* insn_code;
   int val;
-  extern rtx ix_reg;
 
   if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
     {
   "")
 
 (define_insn "*subsi3"
-  [(set (match_operand:SI 0 "register_operand" "=D,D")
-       (minus:SI (match_operand:SI 1 "general_operand" "0,!mui")
-                 (match_operand:SI 2 "general_operand" "!mui,!D")))
-   (clobber (match_scratch:HI 3 "=X,X"))]
+  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
+       (minus:SI (match_operand:SI 1 "general_operand" "0,mi,0,!u,0")
+                 (match_operand:SI 2 "general_operand" "mi,D,!u,D,!mui")))
+   (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
   ""
   "#")
 
    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
 
+(define_split /* "*subsi3" */
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=u")
+       (minus:SI (match_operand:SI 1 "general_operand" "0")
+                 (match_operand:SI 2 "general_operand" "mui")))
+   (clobber (match_scratch:HI 3 "=d"))]
+  "reload_completed && z_replacement_completed == 2
+   && !X_REG_P (operands[0])"
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
+   (set (match_dup 4) (match_dup 3))
+   (set (match_dup 3) (match_dup 6))
+   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
+   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
+   (set (match_dup 6) (match_dup 3))]
+  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
+   operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
+   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
+   operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
+   operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
+   operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
+
 ;;
 ;; - 16-bit Subtract.
 ;;
        (minus:HI (match_operand:HI 1 "register_operand" "0")
                  (match_operand:HI 2 "general_operand" "g")))]
   ""
-  "
-{
-  if (TARGET_M6811 && SP_REG_P (operands[0]))
-    {
-     emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
-                        gen_rtx (SET, VOIDmode,
-                                 operand0,
-                                 gen_rtx (MINUS, HImode,
-                                          operand1, operand2)),
-                       gen_rtx (CLOBBER, VOIDmode,
-                               gen_rtx (SCRATCH, HImode, 0)))));
-     DONE;
-  }
-}")
+  "")
 
 ;;
 ;; Subtract from stack. This is better if we provide a pattern.
 
   if (D_REG_P (operands[3]))
     {
-      output_asm_insn (\"xgdx\", operands);
+      int save_x;
+
+      save_x = !dead_register_here (insn, ix_reg);
+      if (save_x)
+       output_asm_insn (\"xgdx\", operands);
       output_asm_insn (\"tsx\", operands);
       output_asm_insn (\"xgdx\", operands);
       output_asm_insn (\"subd\\t%2\", operands);
       /* The status flags correspond to the addd. xgdx/y and tx/ys do not
          modify the flags.  */
       output_asm_insn (\"txs\", operands);
-      return \"xgdx\";
+      if (save_x)
+        return \"xgdx\";
+      else
+        return \"\";
     }
 
   /* Need to transfer to SP to X,Y and then to D register.
        (match_operator:HI 3 "m68hc11_non_shift_operator"
             [(match_operand:HI 1 "d_register_operand" "%0")
             (match_operand:HI 2 "hard_reg_operand" "*d*A")]))]
-  "z_replacement_completed == 2 && !SP_REG_P (operands[2])"
+  "TARGET_M6811
+   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
   [(set (match_dup 4) (match_dup 2))
    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
   "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
 
+;;
+;; For 68HC12, push the operand[2] value on the stack and do the
+;; logical/arithmetic operation with a pop.
+;;
+(define_split
+  [(set (match_operand:HI 0 "d_register_operand" "=d")
+       (match_operator:HI 3 "m68hc11_non_shift_operator"
+            [(match_operand:HI 1 "d_register_operand" "%0")
+            (match_operand:HI 2 "hard_reg_operand" "*d*A")]))]
+  "TARGET_M6812
+   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
+  [(set (match_dup 4) (match_dup 2))
+   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
+  "operands[4] = gen_rtx (MEM, HImode,
+                         gen_rtx (PRE_DEC, HImode,
+                                  gen_rtx (REG, HImode, HARD_SP_REGNUM)));
+   operands[5] = gen_rtx (MEM, HImode,
+                         gen_rtx (POST_INC, HImode,
+                                  gen_rtx (REG, HImode, HARD_SP_REGNUM)));
+   ")
+
 ;;--------------------------------------------------------------------
 ;; 16-bit Unary operations on X and Y:
 ;;
 ;;             NOT NEG
 ;;
-;; Operations on X or Y registers are split here. Instructions are
+;; Operations on X or Y registers are split here.  Instructions are
 ;; changed into:
 ;;   - xgdx/xgdy instruction pattern,
 ;;   - The same operation on register D,
 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
 ;;
 (define_split
-  [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
+  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 2 "m68hc11_unary_operator"
-            [(match_operand 1 "general_operand" "uim*d*A")]))]
+            [(match_operand 1 "general_operand" "")]))]
   "z_replacement_completed == 2"
   [(set (match_dup 4) (match_dup 5))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
 ;; The shift operators are special and must not appear here.
 ;;
 (define_split
-  [(set (match_operand:QI 0 "d_register_operand" "=d")
+  [(set (match_operand:QI 0 "d_register_operand" "")
        (match_operator:QI 3 "m68hc11_non_shift_operator"
-            [(match_operand:QI 1 "d_register_operand" "%0")
-            (match_operand:QI 2 "hard_reg_operand" "*d*x*y")]))]
+            [(match_operand:QI 1 "d_register_operand" "")
+            (match_operand:QI 2 "hard_reg_operand" "")]))]
   "reload_completed"
   [(set (match_dup 5) (match_dup 6))
    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
 ;;
 ;;             NOT NEG
 ;;
-;; Operations on X or Y registers are split here. Instructions are
+;; Operations on X or Y registers are split here.  Instructions are
 ;; changed into:
 ;;   - xgdx/xgdy instruction pattern,
 ;;   - The same operation on register D,
 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
 ;;
 (define_split
-  [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
+  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (match_operator:QI 2 "m68hc11_unary_operator"
-            [(match_operand:QI 1 "general_operand" "uim*d*x*y")]))]
+            [(match_operand:QI 1 "general_operand" "")]))]
   "z_replacement_completed == 2"
   [(set (match_dup 4) (match_dup 5))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
     operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
 
 (define_insn "addsi_silshr16"
-  [(set (match_operand:SI 0 "register_operand" "=D")
-          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
+  [(set (match_operand:SI 0 "register_operand" "=D,D")
+          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0")
                                (const_int 16))
-                  (match_operand:SI 2 "general_operand" "0")))]
+                  (match_operand:SI 2 "general_operand" "0,m!*u")))]
   ""
   "#")
 
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
+  [(set (match_operand:SI 0 "register_operand" "")
+          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                                (const_int 16))
-                  (match_operand:SI 2 "general_operand" "0")))]
-  "z_replacement_completed == 2"
+                  (match_operand:SI 2 "general_operand" "")))]
+  "z_replacement_completed == 2 && !X_REG_P (operands[1])"
   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
-   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
+   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
+                                           (const_int 0))
+                                  (reg:HI CC_REGNUM)))]
   "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
+                               (const_int 16))
+                  (match_operand:SI 2 "general_operand" "")))]
+  "z_replacement_completed == 2 && X_REG_P (operands[1])"
+  [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+   (set (reg:HI X_REGNUM) (match_dup 3))
+   (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
+   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
+                                           (const_int 0))
+                                  (reg:HI CC_REGNUM)))]
+  "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
+   operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);")
+
 (define_insn "addsi_ashift16"
   [(set (match_operand:SI 0 "register_operand" "=D")
           (plus:SI