OSDN Git Service

* config/h8300/h8300.c (print_operand) : Modify case 'V' and
[pf3gnuchains/gcc-fork.git] / gcc / config / h8300 / h8300.md
index 08a8d2e..513ad4c 100644 (file)
@@ -1,6 +1,7 @@
 ;; GCC machine description for Renesas H8/300
 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
+;; Free Software Foundation, Inc.
 
 ;;   Contributed by Steve Chamberlain (sac@cygnus.com),
 ;;   Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -91,7 +92,7 @@
                                (const_int -126))
                            (le (plus (minus (match_dup 0) (pc))
                                      (symbol_ref "DELAY_SLOT_LENGTH (insn)"))
-                               (const_int 126)))
+                               (const_int 125)))
                       (const_int 2)
                       (if_then_else (and (eq_attr "cpu" "h8300h")
                                          (and (ge (minus (pc) (match_dup 0))
 (define_attr "can_delay" "no,yes"
   (cond [(eq_attr "type" "branch,bitbranch,call")
           (const_string "no")
-        (ne (symbol_ref "get_attr_length (insn)") (const_int 2))
+        (geu (symbol_ref "get_attr_length (insn)") (const_int 2))
           (const_string "no")]
        (const_string "yes")))
 
        (match_operand:QI 1 "general_operand_src" "P4>X,rQi"))]
   "TARGET_H8300SX"
   "@
-    mov.b      %X1,%X0
+    mov.b      %X1:4,%X0
     mov.b      %X1,%X0"
   [(set_attr "length_table" "mov_imm4,movb")
    (set_attr "cc" "set_znv")])
   "TARGET_H8300SX"
   "@
    sub.w       %T0,%T0
-   mov.w       %T1,%T0
-   mov.w       %T1,%T0
+   mov.w       %T1:3,%T0
+   mov.w       %T1:4,%T0
    mov.w       %T1,%T0
    mov.w       %T1,%T0"
   [(set_attr "length_table" "*,*,mov_imm4,short_immediate,movw")
   "TARGET_H8300SX"
   "@
    sub.l       %S0,%S0
-   mov.l       %S1,%S0
+   mov.l       %S1:3,%S0
    mov.l       %S1,%S0
    mov.l       %S1,%S0
    clrmac
 ;; ----------------------------------------------------------------------
 
 (define_insn ""
-  [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "r,U")
-                              (const_int 1)
-                              (match_operand 1 "const_int_operand" "n,n")))]
+  [(set (cc0) (compare
+              (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "r,U")
+                               (const_int 1)
+                               (match_operand 1 "const_int_operand" "n,n"))
+              (const_int 0)))]
   "TARGET_H8300"
   "btst        %Z1,%Y0"
   [(set_attr "length" "2,4")
    (set_attr "cc" "set_zn,set_zn")])
 
 (define_insn ""
-  [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r")
-                              (const_int 1)
-                              (match_operand 1 "const_int_operand" "n")))]
+  [(set (cc0) (compare
+              (zero_extract:HI (match_operand:HI 0 "register_operand" "r")
+                               (const_int 1)
+                               (match_operand 1 "const_int_operand" "n"))
+              (const_int 0)))]
   "TARGET_H8300"
   "btst        %Z1,%Y0"
   [(set_attr "length" "2")
    (set_attr "cc" "set_zn")])
 
 (define_insn_and_split "*tst_extzv_1_n"
-  [(set (cc0)
-       (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
-                        (const_int 1)
-                        (match_operand 1 "const_int_operand" "n,n,n")))
+  [(set (cc0) (compare
+              (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
+                               (const_int 1)
+                               (match_operand 1 "const_int_operand" "n,n,n"))
+              (const_int 0)))
    (clobber (match_scratch:QI 2 "=X,X,&r"))]
   "(TARGET_H8300H || TARGET_H8300S)"
   "@
    && !OK_FOR_U (operands[0])"
   [(set (match_dup 2)
        (match_dup 0))
-   (parallel [(set (cc0) (zero_extract:SI (match_dup 2)
-                                         (const_int 1)
-                                         (match_dup 1)))
+   (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2)
+                                                  (const_int 1)
+                                                  (match_dup 1))
+                                 (const_int 0)))
              (clobber (scratch:QI))])]
   ""
   [(set_attr "length" "2,8,10")
    (set_attr "cc" "set_zn,set_zn,set_zn")])
 
 (define_insn ""
-  [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
-                              (const_int 1)
-                              (match_operand 1 "const_int_operand" "n")))]
+  [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+                                       (const_int 1)
+                                       (match_operand 1 "const_int_operand" "n"))
+                      (const_int 0)))]
   "(TARGET_H8300H || TARGET_H8300S)
    && INTVAL (operands[1]) <= 15"
   "btst        %Z1,%Y0"
    (set_attr "cc" "set_zn")])
 
 (define_insn_and_split "*tstsi_upper_bit"
-  [(set (cc0)
-       (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
-                        (const_int 1)
-                        (match_operand 1 "const_int_operand" "n")))
+  [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+                                       (const_int 1)
+                                       (match_operand 1 "const_int_operand" "n"))
+                      (const_int 0)))
    (clobber (match_scratch:SI 2 "=&r"))]
   "(TARGET_H8300H || TARGET_H8300S)
    && INTVAL (operands[1]) >= 16"
                        (const_int -65536))
                (lshiftrt:SI (match_dup 0)
                             (const_int 16))))
-   (set (cc0)
-       (zero_extract:SI (match_dup 2)
-                        (const_int 1)
-                        (match_dup 3)))]
+   (set (cc0) (compare (zero_extract:SI (match_dup 2)
+                                       (const_int 1)
+                                       (match_dup 3))
+                      (const_int 0)))]
   "operands[3] = GEN_INT (INTVAL (operands[1]) - 16);")
 
 (define_insn "*tstsi_variable_bit"
-  [(set (cc0)
-       (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
-                        (const_int 1)
-                        (and:SI (match_operand:SI 1 "register_operand" "r")
-                                (const_int 7))))]
+  [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+                                       (const_int 1)
+                                       (and:SI (match_operand:SI 1 "register_operand" "r")
+                                               (const_int 7)))
+                      (const_int 0)))]
   "TARGET_H8300H || TARGET_H8300S"
   "btst        %w1,%w0"
   [(set_attr "length" "2")
 
 (define_insn_and_split "*tstsi_variable_bit_qi"
   [(set (cc0)
-       (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>"))
-                        (const_int 1)
-                        (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
-                                (const_int 7))))
+       (compare
+        (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>"))
+                         (const_int 1)
+                         (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
+                                 (const_int 7)))
+         (const_int 0)))
    (clobber (match_scratch:QI 2 "=X,X,&r"))]
   "(TARGET_H8300H || TARGET_H8300S)"
   "@
    && !OK_FOR_U (operands[0])"
   [(set (match_dup 2)
        (match_dup 0))
-   (parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2))
-                                         (const_int 1)
-                                         (and:SI (match_dup 1)
-                                                 (const_int 7))))
+   (parallel [(set (cc0) (compare (zero_extract:SI (zero_extend:SI (match_dup 2))
+                                                  (const_int 1)
+                                                  (and:SI (match_dup 1)
+                                                          (const_int 7)))
+                                 (const_int 0)))
              (clobber (scratch:QI))])]
   ""
   [(set_attr "length" "2,8,10")
    (set_attr "cc" "set_zn,set_zn,set_zn")])
 
-(define_insn "tstqi"
-  [(set (cc0) (match_operand:QI 0 "register_operand" "r"))]
+(define_insn "*tstqi"
+  [(set (cc0) (compare (match_operand:QI 0 "register_operand" "r")
+                      (const_int 0)))]
   ""
   "mov.b       %X0,%X0"
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
-(define_insn "tsthi"
-  [(set (cc0) (match_operand:HI 0 "register_operand" "r"))]
+(define_insn "*tsthi"
+  [(set (cc0) (compare (match_operand:HI 0 "register_operand" "r")
+                      (const_int 0)))]
   ""
   "mov.w       %T0,%T0"
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
 (define_insn "*tsthi_upper"
-  [(set (cc0)
-       (and:HI (match_operand:HI 0 "register_operand" "r")
-               (const_int -256)))]
+  [(set (cc0) (compare (and:HI (match_operand:HI 0 "register_operand" "r")
+                              (const_int -256))
+                      (const_int 0)))]
   ""
   "mov.b       %t0,%t0"
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
-(define_insn "tstsi"
-  [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
+(define_insn "*tstsi"
+  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r")
+                      (const_int 0)))]
   "TARGET_H8300H || TARGET_H8300S"
   "mov.l       %S0,%S0"
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
 (define_insn "*tstsi_upper"
-  [(set (cc0)
-       (and:SI (match_operand:SI 0 "register_operand" "r")
-               (const_int -65536)))]
+  [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "r")
+                              (const_int -65536))
+                      (const_int 0)))]
   ""
   "mov.w       %e0,%e0"
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
-(define_insn "cmpqi"
+(define_insn "*cmpqi"
   [(set (cc0)
        (compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
                 (match_operand:QI 1 "h8300_src_operand" "rQi")))]
   [(set_attr "length_table" "addb")
    (set_attr "cc" "compare")])
 
-(define_expand "cmphi"
-  [(set (cc0)
-       (compare (match_operand:HI 0 "h8300_dst_operand" "")
-                (match_operand:HI 1 "h8300_src_operand" "")))]
-  ""
-  "
-{
-  /* Force operand1 into a register if we're compiling
-     for the H8/300.  */
-  if (GET_CODE (operands[1]) != REG && TARGET_H8300)
-    operands[1] = force_reg (HImode, operands[1]);
-}")
-
 (define_insn "*cmphi_h8300_znvc"
   [(set (cc0)
        (compare (match_operand:HI 0 "register_operand" "r")
        (compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ")
                 (match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))]
   "TARGET_H8300H || TARGET_H8300S"
-  "cmp.w       %T1,%T0"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+      if (!TARGET_H8300SX)
+       return \"cmp.w  %T1,%T0\";
+      else
+       return \"cmp.w  %T1:3,%T0\";
+    case 1:
+      return \"cmp.w   %T1,%T0\";
+    default:
+      gcc_unreachable ();
+      }
+}"
   [(set_attr "length_table" "short_immediate,addw")
    (set_attr "cc" "compare,compare")])
 
        (compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ")
                 (match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))]
   "TARGET_H8300H || TARGET_H8300S"
-  "cmp.l       %S1,%S0"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+      if (!TARGET_H8300SX)
+       return \"cmp.l  %S1,%S0\";
+      else
+       return \"cmp.l  %S1:3,%S0\";
+    case 1:
+      return \"cmp.l   %S1,%S0\";
+    default:
+      gcc_unreachable ();
+    }
+}"
   [(set_attr "length" "2,*")
    (set_attr "length_table" "*,addl")
    (set_attr "cc" "compare,compare")])
                 (match_operand:HI 2 "h8300_src_operand" "P3>X,P3<X,J,rQi")))]
   "TARGET_H8300SX && h8300_operands_match_p (operands)"
   "@
-   add.w       %T2,%T0
-   sub.w       %G2,%T0
+   add.w       %T2:3,%T0
+   sub.w       %G2:3,%T0
    add.b       %t2,%t0
    add.w       %T2,%T0"
   [(set_attr "length_table" "short_immediate,short_immediate,*,addw")
 ;; ----------------------------------------------------------------------
 ;; AND INSTRUCTIONS
 ;; ----------------------------------------------------------------------
+(define_insn "bclrqi_msx"
+  [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU")
+       (and:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:QI 2 "single_zero_operand" "Y0")))]
+  "TARGET_H8300SX"
+  "bclr\\t%W2,%0"
+  [(set_attr "length" "8")])
+
+(define_split
+  [(set (match_operand:HI 0 "bit_register_indirect_operand" "=U")
+       (and:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:HI 2 "single_zero_operand" "Y0")))]
+  "TARGET_H8300SX"
+  [(set (match_dup 0)
+       (and:QI (match_dup 1)
+               (match_dup 2)))]
+{
+  operands[0] = adjust_address (operands[0], QImode, 1);
+  operands[1] = adjust_address (operands[1], QImode, 1);
+})
 
+(define_insn "bclrhi_msx"
+  [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m")
+       (and:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:HI 2 "single_zero_operand" "Y0")))]
+  "TARGET_H8300SX"
+  "bclr\\t%W2,%0"
+  [(set_attr "length" "8")])
 (define_insn "*andqi3_2"
   [(set (match_operand:QI 0 "bit_operand" "=rQ,r")
        (and:QI (match_operand:QI 1 "bit_operand" "%0,WU")
 ;; ----------------------------------------------------------------------
 ;; OR INSTRUCTIONS
 ;; ----------------------------------------------------------------------
+(define_insn "bsetqi_msx"
+  [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU")
+       (ior:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:QI 2 "single_one_operand" "Y2")))]
+  "TARGET_H8300SX" 
+  "bset\\t%V2,%0"
+  [(set_attr "length" "8")])
+
+(define_split
+  [(set (match_operand:HI 0 "bit_register_indirect_operand" "=U")
+       (ior:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:HI 2 "single_one_operand" "Y2")))]
+  "TARGET_H8300SX"
+  [(set (match_dup 0)
+       (ior:QI (match_dup 1)
+               (match_dup 2)))]
+{
+  operands[0] = adjust_address (operands[0], QImode, 1);
+  operands[1] = adjust_address (operands[1], QImode, 1);
+})
+
+(define_insn "bsethi_msx"
+  [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m")
+       (ior:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:HI 2 "single_one_operand" "Y2")))]
+  "TARGET_H8300SX"
+  "bset\\t%V2,%0"
+  [(set_attr "length" "8")])
 
 (define_insn "iorqi3_1"
   [(set (match_operand:QI 0 "bit_operand" "=rQ,U")
 ;; ----------------------------------------------------------------------
 ;; XOR INSTRUCTIONS
 ;; ----------------------------------------------------------------------
+(define_insn "bnotqi_msx"
+  [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU")
+       (xor:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:QI 2 "single_one_operand" "Y2")))]
+  "TARGET_H8300SX"
+  "bnot\\t%V2,%0"
+  [(set_attr "length" "8")])
+
+(define_split
+  [(set (match_operand:HI 0 "bit_register_indirect_operand" "=U")
+       (xor:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:HI 2 "single_one_operand" "Y2")))]
+  "TARGET_H8300SX"
+  [(set (match_dup 0)
+       (xor:QI (match_dup 1)
+               (match_dup 2)))]
+{
+  operands[0] = adjust_address (operands[0], QImode, 1);
+  operands[1] = adjust_address (operands[1], QImode, 1);
+})
+
+(define_insn "bnothi_msx"
+  [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m")
+       (xor:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+               (match_operand:HI 2 "single_one_operand" "Y2")))]
+  "TARGET_H8300SX"
+  "bnot\\t%V2,%0"
+  [(set_attr "length" "8")])
 
 (define_insn "xorqi3_1"
   [(set (match_operand:QI 0 "bit_operand" "=r,U")
 
 ;; Conditional jump instructions
 
-(define_expand "ble"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (LE, operands[0]); DONE;")
-
-(define_expand "bleu"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (LEU, operands[0]); DONE;")
-
-(define_expand "bge"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (GE, operands[0]); DONE;")
-
-(define_expand "bgeu"
-  [(match_operand 0 "" "")]
+(define_expand "cbranchqi4"
+  [(use (match_operator 0 "ordered_comparison_operator"
+         [(match_operand:QI 1 "h8300_dst_operand" "")
+          (match_operand:QI 2 "h8300_src_operand" "")]))
+   (use (match_operand 3 ""))]
   ""
-  "h8300_expand_branch (GEU, operands[0]); DONE;")
+  "h8300_expand_branch (operands); DONE;")
 
-(define_expand "blt"
-  [(match_operand 0 "" "")]
+(define_expand "cbranchhi4"
+  [(use (match_operator 0 "ordered_comparison_operator"
+         [(match_operand:HI 1 "h8300_dst_operand" "")
+          (match_operand:HI 2 "h8300_src_operand" "")]))
+   (use (match_operand 3 ""))]
   ""
-  "h8300_expand_branch (LT, operands[0]); DONE;")
-
-(define_expand "bltu"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (LTU, operands[0]); DONE;")
-
-(define_expand "bgt"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (GT, operands[0]); DONE;")
-
-(define_expand "bgtu"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (GTU, operands[0]); DONE;")
-
-(define_expand "beq"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (EQ, operands[0]); DONE;")
+  "
+{
+  /* Force operand1 into a register if we're compiling
+     for the H8/300.  */
+  if ((GET_CODE (operands[2]) != REG && operands[2] != const0_rtx)
+      && TARGET_H8300)
+    operands[2] = force_reg (HImode, operands[2]);
+  h8300_expand_branch (operands); DONE;
+}")
 
-(define_expand "bne"
-  [(match_operand 0 "" "")]
-  ""
-  "h8300_expand_branch (NE, operands[0]); DONE;")
+(define_expand "cbranchsi4"
+  [(use (match_operator 0 "ordered_comparison_operator"
+         [(match_operand:SI 1 "h8300_dst_operand" "")
+          (match_operand:SI 2 "h8300_src_operand" "")]))
+   (use (match_operand 3 ""))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "h8300_expand_branch (operands); DONE;")
 
 (define_insn "branch_true"
   [(set (pc)
    (clobber (match_operand:QI 3 "register_operand" ""))]
   "epilogue_completed
    && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
-  [(set (cc0)
-       (match_dup 1))
+  [(set (cc0) (compare (match_dup 1)
+                      (const_int 0)))
    (set (pc)
         (if_then_else (le (cc0) (const_int 0))
                      (label_ref (match_dup 5))
       (clobber (scratch:QI))])
    (set (match_dup 1)
        (plus:QI (match_dup 1) (const_int -1)))
-   (set (cc0)
-       (match_dup 1))
+   (set (cc0) (compare (match_dup 1)
+                      (const_int 0)))
    (set (pc)
         (if_then_else (ne (cc0) (const_int 0))
                      (label_ref (match_dup 4))
    && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
   [(set (match_dup 3)
        (match_dup 1))
-   (set (cc0)
-       (match_dup 3))
+   (set (cc0) (compare (match_dup 3)
+                      (const_int 0)))
    (set (pc)
         (if_then_else (le (cc0) (const_int 0))
                      (label_ref (match_dup 5))
       (clobber (scratch:QI))])
    (set (match_dup 3)
        (plus:QI (match_dup 3) (const_int -1)))
-   (set (cc0)
-       (match_dup 3))
+   (set (cc0) (compare (match_dup 3)
+                      (const_int 0)))
    (set (pc)
         (if_then_else (ne (cc0) (const_int 0))
                      (label_ref (match_dup 4))
                                 (match_operand:HI 3 "const_int_operand" "n"))
                         (const_int 1)
                         (match_operand:HI 2 "const_int_operand" "n")))]
-  "TARGET_H8300
+  "(TARGET_H8300 || TARGET_H8300SX)
    && (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
   "sub.w       %0,%0\;bild     %Z2,%Y1\;bst    #0,%X0"
   [(set_attr "length" "8")])
   if (GET_CODE (operands[0]) == MEM
       || GET_CODE (operands[3]) == MEM)
     FAIL;
+
+  if (GET_CODE (operands[3]) != REG)
+    operands[3] = force_reg (HImode, operands[3]);
 }")
 
 (define_insn ""
   [(set_attr "cc" "none_0hit")
    (set_attr "length_table" "bitfield")])
 
-(define_expand "seq"
-  [(set (match_operand:HI 0 "register_operand" "")
-       (eq:HI (cc0) (const_int 0)))]
+(define_expand "cstoreqi4"
+  [(use (match_operator 1 "eqne_operator"
+         [(match_operand:QI 2 "h8300_dst_operand" "")
+          (match_operand:QI 3 "h8300_src_operand" "")]))
+   (clobber (match_operand:HI 0 "register_operand"))]
   "TARGET_H8300SX"
-  "")
+  "h8300_expand_store (operands); DONE;")
 
-(define_expand "sne"
-  [(set (match_operand:HI 0 "register_operand" "")
-       (ne:HI (cc0) (const_int 0)))]
+(define_expand "cstorehi4"
+  [(use (match_operator 1 "eqne_operator"
+         [(match_operand:HI 2 "h8300_dst_operand" "")
+          (match_operand:HI 3 "h8300_src_operand" "")]))
+   (clobber (match_operand:HI 0 "register_operand"))]
   "TARGET_H8300SX"
-  "")
+  "h8300_expand_store (operands); DONE;")
+
+(define_expand "cstoresi4"
+  [(use (match_operator 1 "eqne_operator"
+         [(match_operand:SI 2 "h8300_dst_operand" "")
+          (match_operand:SI 3 "h8300_src_operand" "")]))
+   (clobber (match_operand:HI 0 "register_operand"))]
+  "TARGET_H8300SX"
+  "h8300_expand_store (operands); DONE;")
 
 (define_insn "*bstzhireg"
   [(set (match_operand:HI 0 "register_operand" "=r")
   [(set (cc0) (match_dup 5))
    (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1))
        (match_op_dup:QI 2 [(cc0) (const_int 0)]))]
-  "
-{
-  if (operands[4] == const0_rtx && GET_CODE (operands[3]) == REG)
-    operands[5] = operands[3];
-  else
-    operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);
-}"
+  "operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);"
   [(set_attr "cc" "set_znv,compare")])
    
 (define_insn "*bstz"
        (if_then_else:QI
         (match_op_dup 1 [(cc0) (const_int 0)])
         (ior:QI (match_dup 4) (match_dup 5)) (match_dup 4)))]
-  "
-{
-  if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
-    operands[6] = operands[2];
-  else
-    operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+  "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
   [(set_attr "cc" "set_znv,compare")])
    
 (define_insn "*condbset"
        (if_then_else:QI
         (match_op_dup 1 [(cc0) (const_int 0)])
         (and:QI (match_dup 4) (match_dup 5)) (match_dup 4)))]
-  "
-{
-  if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
-    operands[6] = operands[2];
-  else
-    operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+  "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
   [(set_attr "cc" "set_znv,compare")])
    
 (define_insn "*condbclr"
                 (ashift:QI (const_int 1)
                            (match_operand:QI 5 "register_operand" "r,r")))
         (match_dup 4)))]
-  "
-{
-  if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
-    operands[6] = operands[2];
-  else
-    operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+  "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
   [(set_attr "cc" "set_znv,compare")])
    
 (define_insn "*condbsetreg"
                 (ashift:QI (const_int 1)
                            (match_operand:QI 5 "register_operand" "r,r")))
         (match_dup 4)))]
-  "
-{
-  if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
-    operands[6] = operands[2];
-  else
-    operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+  "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
   [(set_attr "cc" "set_znv,compare")])
    
 (define_insn "*condbclrreg"
   "(TARGET_H8300H || TARGET_H8300S)"
   "#"
   "&& reload_completed"
-  [(set (cc0)
-       (zero_extract:SI (match_dup 1)
-                        (const_int 1)
-                        (const_int 0)))
+  [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+                                       (const_int 1)
+                                       (const_int 0))
+                      (const_int 0)))
    (set (pc)
         (if_then_else (eq (cc0)
                          (const_int 0))
   "(TARGET_H8300H || TARGET_H8300S)"
   "#"
   "&& reload_completed"
-  [(set (cc0)
-       (zero_extract:SI (match_dup 1)
-                        (const_int 1)
-                        (const_int 0)))
+  [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+                                       (const_int 1)
+                                       (const_int 0))
+                      (const_int 0)))
    (set (pc)
         (if_then_else (ne (cc0)
                          (const_int 0))
   ""
   "#"
   ""
-  [(set (cc0)
-       (match_dup 0))
+  [(set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (ge (cc0)
                          (const_int 0))
   ""
   "#"
   ""
-  [(set (cc0)
-       (match_dup 0))
+  [(set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (lt (cc0)
                          (const_int 0))
   [(set (match_operand:HI 0 "register_operand" "")
        (plus:HI (match_dup 0)
                 (match_operand 1 "incdec_operand" "")))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_operator 3 "eqne_operator"
                        [(cc0) (const_int 0)])
        (unspec:HI [(match_dup 0)
                    (match_dup 1)]
                   UNSPEC_INCDEC))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
   [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (match_dup 0)
                 (match_operand 1 "incdec_operand" "")))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_operator 3 "eqne_operator"
                        [(cc0) (const_int 0)])
        (unspec:SI [(match_dup 0)
                    (match_dup 1)]
                   UNSPEC_INCDEC))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
 
 (define_peephole2
   [(parallel [(set (cc0)
-                  (zero_extract:SI (match_operand:QI 0 "register_operand" "")
-                                   (const_int 1)
-                                   (const_int 7)))
+                  (compare (zero_extract:SI (match_operand:QI 0 "register_operand" "")
+                                            (const_int 1)
+                                            (const_int 7))
+                           (const_int 0)))
              (clobber (scratch:QI))])
    (set (pc)
        (if_then_else (match_operator 1 "eqne_operator"
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "(TARGET_H8300H || TARGET_H8300S)"
-  [(set (cc0)
-        (match_dup 0))
+  [(set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
   "operands[3] = gen_lowpart (HImode, operands[0]);
    operands[4] = gen_lowpart (HImode, operands[1]);")
 
+;; Convert a memory comparison to a move if there is a scratch register.
+
+(define_peephole2
+  [(match_scratch:QI 1 "r")
+   (set (cc0)
+       (compare (match_operand:QI 0 "memory_operand" "")
+                (const_int 0)))]
+  ""
+  [(set (match_dup 1)
+       (match_dup 0))
+   (set (cc0) (compare (match_dup 1)
+                      (const_int 0)))]
+  "")
+
+(define_peephole2
+  [(match_scratch:HI 1 "r")
+   (set (cc0)
+       (compare (match_operand:HI 0 "memory_operand" "")
+                (const_int 0)))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  [(set (match_dup 1)
+       (match_dup 0))
+   (set (cc0) (compare (match_dup 1)
+                      (const_int 0)))]
+  "")
+
+(define_peephole2
+  [(match_scratch:SI 1 "r")
+   (set (cc0)
+       (compare (match_operand:SI 0 "memory_operand" "")
+                (const_int 0)))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  [(set (match_dup 1)
+       (match_dup 0))
+   (set (cc0) (compare (match_dup 1)
+                      (const_int 0)))]
+  "")
+
+
 ;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve
 ;; the equivalent with shorter sequences.  Here is the summary.  Cases
 ;; are grouped for each define_peephole2.
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "(TARGET_H8300H || TARGET_H8300S)
+   && INTVAL (operands[1]) != 0
    && peep2_reg_dead_p (1, operands[0])"
   [(set (match_dup 0)
        (unspec:HI [(match_dup 0)
                    (match_dup 4)]
                   UNSPEC_INCDEC))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
                   (ashiftrt:HI (match_dup 0)
                                (match_dup 4)))
              (clobber (scratch:QI))])
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 2)
                      (label_ref (match_dup 3))
                   (ashiftrt:HI (match_dup 0)
                                (match_dup 4)))
              (clobber (scratch:QI))])
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 5)
                      (label_ref (match_dup 3))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "TARGET_H8300H || TARGET_H8300S"
-  [(set (cc0)
-       (and:HI (match_dup 0)
-               (const_int -256)))
+  [(set (cc0) (compare (and:HI (match_dup 0)
+                              (const_int -256))
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 1)
                      (label_ref (match_dup 2))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "TARGET_H8300H || TARGET_H8300S"
-  [(set (cc0)
-       (and:HI (match_dup 0)
-               (const_int -256)))
+  [(set (cc0) (compare (and:HI (match_dup 0)
+                              (const_int -256))
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 3)
                      (label_ref (match_dup 2))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "(TARGET_H8300H || TARGET_H8300S)
+   && INTVAL (operands[1]) != 0
    && peep2_reg_dead_p (1, operands[0])"
   [(set (match_dup 0)
        (unspec:SI [(match_dup 0)
                    (match_dup 4)]
                   UNSPEC_INCDEC))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
   [(set (match_dup 0)
        (plus:SI (match_dup 0)
                 (match_dup 4)))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
    && ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1])
        || (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1])
        || INTVAL (operands[1]) == 0x0000ffff)
+   && INTVAL (operands[1]) != 0
    && INTVAL (operands[1]) != 1
    && INTVAL (operands[1]) != 2"
   [(set (match_dup 0)
        (xor:SI (match_dup 0)
                (match_dup 1)))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
                (match_dup 4)))
    (set (match_dup 0)
        (not:SI (match_dup 0)))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
        (unspec:SI [(match_dup 0)
                    (const_int -1)]
                   UNSPEC_INCDEC))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
                   (ashiftrt:SI (match_dup 4)
                                (match_dup 5)))
              (clobber (scratch:QI))])
-   (set (cc0)
-       (match_dup 4))
+   (set (cc0) (compare (match_dup 4)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 2)
                      (label_ref (match_dup 3))
                   (ashiftrt:SI (match_dup 4)
                                (match_dup 5)))
              (clobber (scratch:QI))])
-   (set (cc0)
-       (match_dup 4))
+   (set (cc0) (compare (match_dup 4)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 6)
                      (label_ref (match_dup 3))
                   (ashiftrt:SI (match_dup 0)
                                (match_dup 4)))
              (clobber (scratch:QI))])
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 2)
                      (label_ref (match_dup 3))
                   (ashiftrt:SI (match_dup 0)
                                (match_dup 4)))
              (clobber (scratch:QI))])
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 5)
                      (label_ref (match_dup 3))
   [(set (match_dup 0)
        (and:SI (match_dup 0)
                (match_dup 4)))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 2)
                      (label_ref (match_dup 3))
   [(set (match_dup 0)
        (and:SI (match_dup 0)
                (match_dup 4)))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 5)
                      (label_ref (match_dup 3))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "TARGET_H8300H || TARGET_H8300S"
-  [(set (cc0)
-       (and:SI (match_dup 0)
-               (const_int -65536)))
+  [(set (cc0) (compare (and:SI (match_dup 0)
+                              (const_int -65536))
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 1)
                      (label_ref (match_dup 2))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "TARGET_H8300H || TARGET_H8300S"
-  [(set (cc0)
-       (and:SI (match_dup 0)
-               (const_int -65536)))
+  [(set (cc0) (compare (and:SI (match_dup 0)
+                              (const_int -65536))
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_dup 3)
                      (label_ref (match_dup 2))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
   "(TARGET_H8300H || TARGET_H8300S)
+   && INTVAL (operands[1]) != 0
    && !peep2_reg_dead_p (1, operands[0])
    && !same_cmp_following_p (insn)"
   [(set (match_dup 4)
        (unspec:SI [(match_dup 4)
                    (match_dup 5)]
                   UNSPEC_INCDEC))
-   (set (cc0)
-       (match_dup 4))
+   (set (cc0) (compare (match_dup 4)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
   [(set (match_operand:HI 0 "register_operand" "")
        (and:HI (match_dup 0)
                (match_operand:HI 1 "const_int_qi_operand" "")))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_operator 3 "eqne_operator"
                        [(cc0) (const_int 0)])
   [(set (match_dup 4)
        (and:QI (match_dup 4)
                (match_dup 5)))
-   (set (cc0)
-       (match_dup 4))
+   (set (cc0) (compare (match_dup 4)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
   [(set (match_operand:SI 0 "register_operand" "")
        (and:SI (match_dup 0)
                (match_operand:SI 1 "const_int_qi_operand" "")))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_operator 3 "eqne_operator"
                        [(cc0) (const_int 0)])
   [(set (match_dup 4)
        (and:QI (match_dup 4)
                (match_dup 5)))
-   (set (cc0)
-       (match_dup 4))
+   (set (cc0) (compare (match_dup 4)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
   [(set (match_operand:SI 0 "register_operand" "")
        (and:SI (match_dup 0)
                (match_operand:SI 1 "const_int_hi_operand" "")))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_operator 3 "eqne_operator"
                        [(cc0) (const_int 0)])
   [(set (match_dup 4)
        (and:HI (match_dup 4)
                (match_dup 5)))
-   (set (cc0)
-       (match_dup 4))
+   (set (cc0) (compare (match_dup 4)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
                      (label_ref (match_dup 2))
    (set (match_dup 0)
        (xor:SI (match_dup 0)
                (match_operand:SI 2 "const_int_qi_operand" "")))
-   (set (cc0)
-       (match_dup 0))
+   (set (cc0) (compare (match_dup 0)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_operator 4 "eqne_operator"
                        [(cc0) (const_int 0)])
    (set (match_dup 5)
        (xor:QI (match_dup 5)
                (match_dup 7)))
-   (set (cc0)
-       (match_dup 5))
+   (set (cc0) (compare (match_dup 5)
+                      (const_int 0)))
    (set (pc)
        (if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
                      (label_ref (match_dup 3))
                 (match_operand 2 "h8300_src_operand" "")))]
   "TARGET_H8300SX
    && peep2_reg_dead_p (2, operands[0])
-   && !reg_overlap_mentioned_p (operands[0], operands[2])"
+   && !reg_overlap_mentioned_p (operands[0], operands[2])
+   && operands[2] != const0_rtx"
   [(set (cc0)
        (compare (match_dup 1)
                 (match_dup 2)))])