OSDN Git Service

* config/h8300/h8300.md (addhi3_incdec): Change the name to
[pf3gnuchains/gcc-fork.git] / gcc / config / h8300 / h8300.md
index b0dba1a..254d382 100644 (file)
@@ -1,24 +1,24 @@
 ;; GCC machine description for Hitachi H8/300
 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002 Free Software Foundation, Inc.
+;; 2001, 2002, 2003 Free Software Foundation, Inc.
 
 ;;   Contributed by Steve Chamberlain (sac@cygnus.com),
 ;;   Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
 
-;; This file is part of GNU CC.
+;; This file is part of GCC.
 
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
 
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING.  If not, write to
+;; along with GCC; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
 ;; ----------------------------------------------------------------------
 
 (define_constants
+  [(UNSPEC_INCDEC      0)
+   (UNSPEC_MONITOR     1)])
+
+(define_constants
   [(SC_REG      3)
    (FP_REG      6)
    (SP_REG      7)
                   (plus:HI (reg:HI SP_REG) (const_int -2)))
              (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1)))
                   (match_operand:QI 0 "register_operand" "r"))])]
-  "TARGET_H8300"
+  "TARGET_H8300
+   && REGNO (operands[0]) != SP_REG"
   "mov.w\\t%T0,@-r7"
   [(set_attr "length" "2")
    (set_attr "cc" "clobber")])
                   (plus:SI (reg:SI SP_REG) (const_int -4)))
              (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
                   (match_operand:QI 0 "register_operand" "r"))])]
-  "TARGET_H8300H || TARGET_H8300S"
+  "(TARGET_H8300H || TARGET_H8300S)
+   && REGNO (operands[0]) != SP_REG"
   "mov.l\\t%S0,@-er7"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
 (define_expand "pushhi1_h8300"
   [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
        (match_operand:HI 0 "register_operand" ""))]
-  "TARGET_H8300"
+  "TARGET_H8300
+   && REGNO (operands[0]) != SP_REG"
   "")
 
 (define_insn "pushhi1_h8300hs"
                   (plus:SI (reg:SI SP_REG) (const_int -4)))
              (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
                   (match_operand:HI 0 "register_operand" "r"))])]
-  "TARGET_H8300H || TARGET_H8300S"
+  "(TARGET_H8300H || TARGET_H8300S)
+   && REGNO (operands[0]) != SP_REG"
   "mov.l\\t%S0,@-er7"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
        || register_operand (operands[1], SImode))"
   "*
 {
-  int rn = -1;
+  unsigned int rn = -1;
   switch (which_alternative)
     {
     case 0:
   "*
 {
   /* Copy of the movsi stuff.  */
-  int rn = -1;
+  unsigned int rn = -1;
   switch (which_alternative)
     {
     case 0:
    (set_attr "cc" "clobber")])
 
 (define_insn "movsi_h8300hs"
-  [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,r,m,<,r,*a,*a,r")
-       (match_operand:SI 1 "general_operand_src" "I,r,i,m,r,r,>,I,r,*a"))]
+  [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r")
+       (match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))]
   "(TARGET_H8300S || TARGET_H8300H)
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))
     }
    return \"mov.l      %S1,%S0\";
 }"
-  [(set_attr "length" "2,2,6,10,10,4,4,2,6,4")
+  [(set_attr "length" "2,2,6,4,4,10,10,2,6,4")
    (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
 
 (define_insn "movsf_h8300h"
   [(set_attr "length" "2")
    (set_attr "cc" "set_zn")])
 
-(define_insn ""
-  [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_memory_operand" "r,U")
+(define_insn "*tst_extzv_bitqi_1_n"
+  [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_operand" "r,U")
                               (const_int 1)
                               (match_operand 1 "const_int_operand" "n,n")))]
-  "TARGET_H8300H || TARGET_H8300S"
+  "(TARGET_H8300H || TARGET_H8300S)
+   && INTVAL (operands[1]) != 7"
   "btst        %Z1,%Y0"
   [(set_attr "length" "2,8")
    (set_attr "cc" "set_zn,set_zn")])
 
+(define_insn_and_split "*tst_extzv_memqi_1_n"
+  [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
+                              (const_int 1)
+                              (match_operand 1 "const_int_operand" "n")))
+   (clobber (match_scratch:QI 2 "=&r"))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && !EXTRA_CONSTRAINT (operands[0], 'U')
+   && INTVAL (operands[1]) != 7"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2)
+       (match_dup 0))
+   (set (cc0) (zero_extract:SI (match_dup 2)
+                              (const_int 1)
+                              (match_dup 1)))]
+  "")
+
 (define_insn ""
   [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
                               (const_int 1)
 
 (define_insn "cmpqi"
   [(set (cc0)
-       (compare:QI (match_operand:QI 0 "register_operand" "r")
-                   (match_operand:QI 1 "nonmemory_operand" "rn")))]
+       (compare (match_operand:QI 0 "register_operand" "r")
+                (match_operand:QI 1 "nonmemory_operand" "rn")))]
   ""
   "cmp.b       %X1,%X0"
   [(set_attr "length" "2")
 
 (define_expand "cmphi"
   [(set (cc0)
-       (compare:HI (match_operand:HI 0 "register_operand" "")
-                   (match_operand:HI 1 "nonmemory_operand" "")))]
+       (compare (match_operand:HI 0 "register_operand" "")
+                (match_operand:HI 1 "nonmemory_operand" "")))]
   ""
   "
 {
     operands[1] = force_reg (HImode, operands[1]);
 }")
 
-(define_insn ""
+(define_insn "*cmphi_h8300"
   [(set (cc0)
-       (compare:HI (match_operand:HI 0 "register_operand" "r")
-                   (match_operand:HI 1 "register_operand" "r")))]
+       (compare (match_operand:HI 0 "register_operand" "r")
+                (match_operand:HI 1 "register_operand" "r")))]
   "TARGET_H8300"
   "cmp.w       %T1,%T0"
   [(set_attr "length" "2")
    (set_attr "cc" "compare")])
 
-(define_insn ""
+(define_insn "*cmphi_h8300hs"
   [(set (cc0)
-       (compare:HI (match_operand:HI 0 "register_operand" "r,r")
-                   (match_operand:HI 1 "nonmemory_operand" "r,n")))]
+       (compare (match_operand:HI 0 "register_operand" "r,r")
+                (match_operand:HI 1 "nonmemory_operand" "r,n")))]
   "TARGET_H8300H || TARGET_H8300S"
   "cmp.w       %T1,%T0"
   [(set_attr "length" "2,4")
 
 (define_insn "cmpsi"
   [(set (cc0)
-       (compare:SI (match_operand:SI 0 "register_operand" "r,r")
-                   (match_operand:SI 1 "nonmemory_operand" "r,i")))]
+       (compare (match_operand:SI 0 "register_operand" "r,r")
+                (match_operand:SI 1 "nonmemory_operand" "r,i")))]
   "TARGET_H8300H || TARGET_H8300S"
   "cmp.l       %S1,%S0"
   [(set_attr "length" "2,6")
   ""
   "")
 
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,&r")
-       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,g")
-                (match_operand:HI 2 "nonmemory_operand" "L,N,n,r,r")))]
+(define_insn "*addhi3_h8300"
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
+       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0")
+                (match_operand:HI 2 "nonmemory_operand" "L,N,J,n,r")))]
   "TARGET_H8300"
   "@
    adds        %2,%T0
    subs        %G2,%T0
+   add.b       %t2,%t0
    add.b       %s2,%s0\;addx   %t2,%t0
-   add.w       %T2,%T0
-   mov.w       %T1,%T0\;add.w  %T2,%T0"
-  [(set_attr "length" "2,2,4,2,6")
-   (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
+   add.w       %T2,%T0"
+  [(set_attr "length" "2,2,2,4,2")
+   (set_attr "cc" "none_0hit,none_0hit,clobber,clobber,set_zn")])
 
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
-       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
-                (match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))]
+;; This splitter is very important to make the stack adjustment
+;; interrupt-safe.  The combination of add.b and addx is unsafe!
+;;
+;; We apply this split after the peephole2 pass so that we won't end
+;; up creating too many adds/subs when a scratch register is
+;; available, which is actually a common case because stack unrolling
+;; tends to happen immediately after a function call.
+
+(define_split
+  [(set (match_operand:HI 0 "stack_pointer_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand 1 "const_int_gt_2_operand" "")))]
+  "TARGET_H8300 && flow2_completed"
+  [(const_int 0)]
+  "split_adds_subs (HImode, operands); DONE;")
+
+(define_peephole2
+  [(match_scratch:HI 2 "r")
+   (set (match_operand:HI 0 "stack_pointer_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand:HI 1 "const_int_ge_8_operand" "")))]
+  "TARGET_H8300"
+  [(set (match_dup 2)
+       (match_dup 1))
+   (set (match_dup 0)
+       (plus:HI (match_dup 0)
+                (match_dup 2)))]
+  "")
+
+(define_insn "*addhi3_h8300hs"
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
+       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0")
+                (match_operand:HI 2 "nonmemory_operand" "L,N,J,n,r")))]
   "TARGET_H8300H || TARGET_H8300S"
   "@
    adds        %2,%S0
    subs        %G2,%S0
+   add.b       %t2,%t0
    add.w       %T2,%T0
    add.w       %T2,%T0"
-  [(set_attr "length" "2,2,4,2")
-   (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+  [(set_attr "length" "2,2,2,4,2")
+   (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
+
+(define_insn "*addhi3_incdec"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+       (unspec:HI [(match_operand:HI 1 "register_operand" "0,0")
+                   (match_operand:HI 2 "incdec_operand" "M,O")]
+                  UNSPEC_INCDEC))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "@
+   inc.w       %2,%T0
+   dec.w       %G2,%T0"
+  [(set_attr "length" "2,2")
+   (set_attr "cc" "set_zn,set_zn")])
 
 (define_split
   [(set (match_operand:HI 0 "register_operand" "")
   "")
 
 (define_insn "addsi_h8300"
-  [(set (match_operand:SI 0 "register_operand" "=r,r,&r")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
-                (match_operand:SI 2 "nonmemory_operand" "n,r,r")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "nonmemory_operand" "n,r")))]
   "TARGET_H8300"
-  "@
-   add %w2,%w0\;addx   %x2,%x0\;addx   %y2,%y0\;addx   %z2,%z0
-   add.w       %f2,%f0\;addx   %y2,%y0\;addx   %z2,%z0
-   mov.w       %f1,%f0\;mov.w  %e1,%e0\;add.w  %f2,%f0\;addx   %y2,%y0\;addx   %z2,%z0"
-  [(set_attr "length" "8,6,10")
-   (set_attr "cc" "clobber")])
+  "* return output_plussi (operands);"
+  [(set (attr "length")
+       (symbol_ref "compute_plussi_length (operands)"))
+   (set (attr "cc")
+       (symbol_ref "compute_plussi_cc (operands)"))])
 
 (define_insn "addsi_h8300h"
-  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
-                (match_operand:SI 2 "nonmemory_operand" "L,N,i,r")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "nonmemory_operand" "i,r")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_plussi (operands);"
+  [(set (attr "length")
+       (symbol_ref "compute_plussi_length (operands)"))
+   (set (attr "cc")
+       (symbol_ref "compute_plussi_cc (operands)"))])
+
+(define_insn "*addsi3_incdec"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (unspec:SI [(match_operand:SI 1 "register_operand" "0,0")
+                   (match_operand:SI 2 "incdec_operand" "M,O")]
+                  UNSPEC_INCDEC))]
   "TARGET_H8300H || TARGET_H8300S"
   "@
-   adds        %2,%S0
-   subs        %G2,%S0
-   add.l       %S2,%S0
-   add.l       %S2,%S0"
-  [(set_attr "length" "2,2,6,2")
-   (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+   inc.l       %2,%S0
+   dec.l       %G2,%S0"
+  [(set_attr "length" "2,2")
+   (set_attr "cc" "set_zn,set_zn")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
                        (match_operand:QI 3 "single_one_operand" "n"))
                (match_operand:QI 1 "register_operand" "0")))]
   ""
-  "bld\\t%V3,%X2\;bst\\t%V3,%X0"
-  [(set_attr "length" "4")
+  "bld\\t%V3,%X2\;bor\\t%V3,%X0\;bst\\t%V3,%X0"
+  [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
 (define_insn "*andorhi3"
   if (INTVAL (operands[3]) > 128)
     {
       operands[3] = GEN_INT (INTVAL (operands[3]) >> 8);
-      return \"bld\\t%V3,%t2\;bst\\t%V3,%t0\";
+      return \"bld\\t%V3,%t2\;bor\\t%V3,%t0\;bst\\t%V3,%t0\";
     }
-  return \"bld\\t%V3,%s2\;bst\\t%V3,%s0\";
+  return \"bld\\t%V3,%s2\;bor\\t%V3,%s0\;bst\\t%V3,%s0\";
 }"
-  [(set_attr "length" "4")
+  [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
 (define_insn "*andorsi3"
   if (INTVAL (operands[3]) > 128)
     {
       operands[3] = GEN_INT (INTVAL (operands[3]) >> 8);
-      return \"bld\\t%V3,%x2\;bst\\t%V3,%x0\";
+      return \"bld\\t%V3,%x2\;bor\\t%V3,%x0\;bst\\t%V3,%x0\";
     }
-  return \"bld\\t%V3,%w2\;bst\\t%V3,%w0\";
+  return \"bld\\t%V3,%w2\;bor\\t%V3,%w0\;bst\\t%V3,%w0\";
 }"
-  [(set_attr "length" "4")
+  [(set_attr "length" "6")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*andorsi3_shift_8"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r")
+                                  (const_int 8))
+                       (const_int 65280))
+               (match_operand:SI 1 "register_operand" "0")))]
+  ""
+  "or.b\\t%w2,%x0"
+  [(set_attr "length" "2")
    (set_attr "cc" "clobber")])
 
 (define_expand "andsi3"
   [(set_attr "length" "2")
    (set_attr "cc" "set_zn")])
 
+(define_expand "negsf2"
+  [(set (match_operand:SF 0 "register_operand" "")
+       (neg:SF (match_operand:SF 1 "register_operand" "")))]
+  ""
+  "")
+
+(define_insn "*negsf2_h8300"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+       (neg:SF (match_operand:SF 1 "register_operand" "0")))]
+  "TARGET_H8300"
+  "xor.b\\t#128,%z0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*negsf2_h8300hs"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+       (neg:SF (match_operand:SF 1 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "xor.w\\t#32768,%e0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "4")])
+\f
+;; ----------------------------------------------------------------------
+;; ABSOLUTE VALUE INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_expand "abssf2"
+  [(set (match_operand:SF 0 "register_operand" "")
+       (abs:SF (match_operand:SF 1 "register_operand" "")))]
+  ""
+  "")
+
+(define_insn "*abssf2_h8300"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+       (abs:SF (match_operand:SF 1 "register_operand" "0")))]
+  "TARGET_H8300"
+  "and.b\\t#127,%z0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*abssf2_h8300hs"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+       (abs:SF (match_operand:SF 1 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "and.w\\t#32767,%e0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "4")])
+\f
 ;; ----------------------------------------------------------------------
 ;; NOT INSTRUCTIONS
 ;; ----------------------------------------------------------------------
   [(set_attr "cc" "none")
    (set_attr "length" "2")])
 
+(define_insn "tablejump_normal_mode"
+   [(set (pc) (match_operand:HI 0 "register_operand" "r"))
+    (use (label_ref (match_operand 1 "" "")))]
+   "(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE"
+   "jmp @%S0"
+   [(set_attr "cc" "none")
+    (set_attr "length" "2")])
+
 ;; This is a define expand, because pointers may be either 16 or 32 bits.
 
 (define_expand "indirect_jump"
   [(set_attr "cc" "none")
    (set_attr "length" "2")])
 
+(define_insn "indirect_jump_normal_mode"
+  [(set (pc) (match_operand:HI 0 "jump_address_operand" "Vr"))]
+  "(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE"
+  "jmp @%S0"
+  [(set_attr "cc" "none")
+   (set_attr "length" "2")])
+
 ;; Call subroutine with no return value.
 
 ;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
    (set_attr "length" "2")])
 \f
 ;; ----------------------------------------------------------------------
+;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_expand "push_h8300"
+  [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
+        (match_operand:HI 0 "register_operand" "=r"))]
+       
+  "TARGET_H8300"
+  "")
+
+(define_expand "push_h8300hs"
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+        (match_operand:SI 0 "register_operand" "=r"))]
+  "TARGET_H8300H && TARGET_H8300S"
+  "")
+
+(define_expand "pop_h8300"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (mem:HI (post_inc:HI (reg:HI SP_REG))))]
+  "TARGET_H8300"
+  "")
+
+(define_expand "pop_h8300hs"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (mem:SI (post_inc:SI (reg:SI SP_REG))))]
+  "TARGET_H8300H && TARGET_H8300S"
+  "")
+
+(define_insn "stm_h8300s_2"
+  [(parallel
+     [(set (reg:SI SP_REG)
+          (plus:SI (reg:SI SP_REG) (const_int -8)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+          (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+          (match_operand:SI 1 "register_operand" ""))])]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+       || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+       || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+  "stm.l\\t%S0-%S1,@-er7"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "stm_h8300s_3"
+  [(parallel
+     [(set (reg:SI SP_REG)
+          (plus:SI (reg:SI SP_REG) (const_int -12)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+          (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+          (match_operand:SI 1 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+          (match_operand:SI 2 "register_operand" ""))])]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0
+       && REGNO (operands[1]) == 1
+       && REGNO (operands[2]) == 2)
+       || (REGNO (operands[0]) == 4
+          && REGNO (operands[1]) == 5
+          && REGNO (operands[2]) == 6))"
+  "stm.l\\t%S0-%S2,@-er7"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "stm_h8300s_4"
+  [(parallel
+     [(set (reg:SI SP_REG)
+          (plus:SI (reg:SI SP_REG) (const_int -16)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+          (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+          (match_operand:SI 1 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+          (match_operand:SI 2 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -16)))
+          (match_operand:SI 3 "register_operand" ""))])]
+  "TARGET_H8300S
+   && REGNO (operands[0]) == 0
+   && REGNO (operands[1]) == 1
+   && REGNO (operands[2]) == 2
+   && REGNO (operands[3]) == 3"
+  "stm.l\\t%S0-%S3,@-er7"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_2"
+  [(parallel
+     [(set (reg:SI SP_REG)
+          (plus:SI (reg:SI SP_REG) (const_int 8)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+          (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (reg:SI SP_REG))
+          (match_operand:SI 1 "register_operand" ""))])]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+       || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+       || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+  "ldm.l\\t@er7+,%S0-%S1"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_3"
+  [(parallel
+     [(set (reg:SI SP_REG)
+          (plus:SI (reg:SI SP_REG) (const_int 12)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8)))
+          (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+          (match_operand:SI 1 "register_operand" ""))
+      (set (mem:SI (reg:SI SP_REG))
+          (match_operand:SI 2 "register_operand" ""))])]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0
+       && REGNO (operands[1]) == 1
+       && REGNO (operands[2]) == 2)
+       || (REGNO (operands[0]) == 4
+          && REGNO (operands[1]) == 5
+          && REGNO (operands[2]) == 6))"
+  "ldm.l\\t@er7+,%S0-%S2"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_4"
+  [(parallel
+     [(set (reg:SI SP_REG)
+          (plus:SI (reg:SI SP_REG) (const_int 16)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 12)))
+          (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8)))
+          (match_operand:SI 1 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+          (match_operand:SI 2 "register_operand" ""))
+      (set (mem:SI (reg:SI SP_REG))
+          (match_operand:SI 3 "register_operand" ""))])]
+  "TARGET_H8300S
+   && REGNO (operands[0]) == 0
+   && REGNO (operands[1]) == 1
+   && REGNO (operands[2]) == 2
+   && REGNO (operands[3]) == 3"
+  "ldm.l\\t@er7+,%S0-%S3"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_expand "return"
+  [(return)]
+  "h8300_can_use_return_insn_p ()"
+  "")
+
+(define_insn "*return_1"
+  [(return)]
+  "reload_completed"
+  "*
+{
+  if (h8300_current_function_interrupt_function_p ())
+    return \"rte\";
+  else
+    return \"rts\";
+}"
+  [(set_attr "cc" "none")
+   (set_attr "length" "2")])
+
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "h8300_expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  "h8300_expand_epilogue ();")
+
+(define_insn "monitor_prologue"
+  [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)]
+  ""
+  "*
+{
+  if (TARGET_H8300)
+    return \"subs\\t#2,r7\;mov.w\\tr0,@-r7\;stc\\tccr,r0l\;mov.b\tr0l,@(2,r7)\;mov.w\\t@r7+,r0\;orc\t#128,ccr\";
+  else if (TARGET_H8300H)
+    return \"mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr\";
+  else if (TARGET_H8300S)
+    return \"stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr\";
+    abort ();
+}"
+  [(set_attr "length" "20")
+   (set_attr "cc" "clobber")])
+\f
+;; ----------------------------------------------------------------------
 ;; EXTEND INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
   ""
   "")
 
-(define_insn ""
+(define_insn "*zero_extendqihi2_h8300"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
        (zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
   "TARGET_H8300"
   "@
   mov.b        #0,%t0
-  mov.b        %R1,%s0\;mov.b  #0,%t0"
+  #"
   [(set_attr "length" "2,10")
    (set_attr "cc" "clobber,clobber")])
 
-(define_insn ""
+(define_insn "*zero_extendqihi2_h8300hs"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
        (zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
   "TARGET_H8300H || TARGET_H8300S"
   "@
   extu.w       %T0
-  mov.b        %R1,%s0\;extu.w %T0"
+  #"
   [(set_attr "length" "2,10")
    (set_attr "cc" "set_znv,set_znv")])
 
+;; Split the zero extension of a general operand (actually a memory
+;; operand) into a load of the operand and the actual zero extension
+;; so that 1) the length will be accurate, and 2) the zero extensions
+;; appearing at the end of basic blocks may be merged.
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (zero_extend:HI (match_operand:QI 1 "general_operand_src" "")))]
+  "reload_completed"
+  [(set (match_dup 2)
+       (match_dup 1))
+   (set (match_dup 0)
+       (zero_extend:HI (match_dup 2)))]
+  "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
+
 ;; The compiler can synthesize a H8/300H variant of this which is
 ;; just as efficient as one that we'd create
 (define_insn "zero_extendqisi2"
   "@
   mov.b        #0,%x0\;sub.w   %e0,%e0
   mov.b        %R1,%w0\;mov.b  #0,%x0\;sub.w   %e0,%e0"
-  [(set_attr "length" "4,6")
+  [(set_attr "length" "4,8")
    (set_attr "cc" "clobber,clobber")])
 
 (define_expand "zero_extendhisi2"
   "")
 
 ;; %e prints the high part of a CONST_INT, not the low part.  Arggh.
-(define_insn ""
+(define_insn "*zero_extendhisi2_h8300"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
        (zero_extend:SI (match_operand:HI 1 "general_operand_src" "0,i,g>")))]
   "TARGET_H8300"
   sub.w        %e0,%e0
   mov.w        %f1,%f0\;sub.w  %e0,%e0
   mov.w        %e1,%f0\;sub.w  %e0,%e0"
-  [(set_attr "length" "2,4,4")
+  [(set_attr "length" "2,4,6")
    (set_attr "cc" "clobber,clobber,clobber")])
 
 (define_insn ""
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
-;; The compiler can synthesize a H8/300H variant of this which is
-;; just as efficient as one that we'd create
-(define_insn "extendqisi2"
+(define_expand "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
+  ""
+  "")
+
+(define_insn "*extendqisi2_h8300"
+  [(set (match_operand:SI 0 "register_operand" "")
        (sign_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))]
   "TARGET_H8300"
   "@
   bld  #7,%w0\;subx    %x0,%x0\;subx   %y0,%y0\;subx   %z0,%z0
   mov.b        %R1,%w0\;bld    #7,%w0\;subx    %x0,%x0\;subx   %y0,%y0\;subx   %z0,%z0"
-  [(set_attr "length" "8,10")
+  [(set_attr "length" "8,12")
    (set_attr "cc" "clobber,clobber")])
 
+;; The following pattern is needed because without the pattern, the
+;; combiner would split (sign_extend:SI (reg:QI)) into into two 24-bit
+;; shifts, one ashift and one ashiftrt.
+
+(define_insn_and_split "*extendqisi2_h8300hs"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2)
+       (sign_extend:HI (match_dup 1)))
+   (set (match_dup 0)
+       (sign_extend:SI (match_dup 2)))]
+  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
+
 (define_expand "extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "")
        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
   ""
   "")
 
-(define_insn ""
+(define_insn "*extendhisi2_h8300"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (sign_extend:SI (match_operand:HI 1 "general_operand_src" "0,g>")))]
   "TARGET_H8300"
   "@
   bld  #7,%x0\;subx    %y0,%y0\;subx   %z0,%z0
   mov.w        %T1,%f0\;bld    #7,%x0\;subx    %y0,%y0\;subx   %z0,%z0"
-  [(set_attr "length" "6,8")
+  [(set_attr "length" "6,10")
    (set_attr "cc" "clobber,clobber")])
 
 (define_insn ""
        (ashift:QI (match_operand:QI 1 "register_operand" "")
                   (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (QImode, ASHIFT, operands)) DONE; else FAIL;")
+  "expand_a_shift (QImode, ASHIFT, operands); DONE;")
 
 (define_expand "ashrqi3"
   [(set (match_operand:QI 0 "register_operand" "")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (QImode, ASHIFTRT, operands)) DONE; else FAIL;")
+  "expand_a_shift (QImode, ASHIFTRT, operands); DONE;")
 
 (define_expand "lshrqi3"
   [(set (match_operand:QI 0 "register_operand" "")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE; else FAIL;")
+  "expand_a_shift (QImode, LSHIFTRT, operands); DONE;")
 
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=r,r")
        (ashift:HI (match_operand:HI 1 "nonmemory_operand" "")
                   (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (HImode, ASHIFT, operands)) DONE; else FAIL;")
+  "expand_a_shift (HImode, ASHIFT, operands); DONE;")
 
 (define_expand "lshrhi3"
   [(set (match_operand:HI 0 "register_operand" "")
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (HImode, LSHIFTRT, operands)) DONE; else FAIL;")
+  "expand_a_shift (HImode, LSHIFTRT, operands); DONE;")
 
 (define_expand "ashrhi3"
   [(set (match_operand:HI 0 "register_operand" "")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE; else FAIL;")
+  "expand_a_shift (HImode, ASHIFTRT, operands); DONE;")
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r,r")
        (ashift:SI (match_operand:SI 1 "general_operand" "")
                   (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (SImode, ASHIFT, operands)) DONE; else FAIL;")
+  "expand_a_shift (SImode, ASHIFT, operands); DONE;")
 
 (define_expand "lshrsi3"
   [(set (match_operand:SI 0 "register_operand" "")
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE; else FAIL;")
+  "expand_a_shift (SImode, LSHIFTRT, operands); DONE;")
 
 (define_expand "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "")
        (ashiftrt:SI (match_operand:SI 1 "general_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE; else FAIL;")
+  "expand_a_shift (SImode, ASHIFTRT, operands); DONE;")
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
   [(set (attr "length")
        (symbol_ref "compute_a_shift_length (insn, operands)"))
    (set_attr "cc" "clobber")])
+
+;; Split a variable shift into a loop.  If the register containing
+;; the shift count dies, then we just use that register.
+
+(define_split
+  [(parallel
+     [(set (match_operand 0 "register_operand" "")
+          (match_operator 2 "nshift_operator"
+            [(match_dup 0)
+             (match_operand:QI 1 "register_operand" "")]))
+      (clobber (match_operand:QI 3 "register_operand" ""))])]
+  "flow2_completed
+   && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
+  [(set (cc0)
+       (match_dup 1))
+   (set (pc)
+        (if_then_else (le (cc0) (const_int 0))
+                     (label_ref (match_dup 5))
+                     (pc)))
+   (match_dup 4)
+   (parallel
+     [(set (match_dup 0)
+          (match_op_dup 2 [(match_dup 0) (const_int 1)]))
+      (clobber (scratch:QI))])
+   (set (match_dup 1)
+       (plus:QI (match_dup 1) (const_int -1)))
+   (set (cc0)
+       (match_dup 1))
+   (set (pc)
+        (if_then_else (ne (cc0) (const_int 0))
+                     (label_ref (match_dup 4))
+                     (pc)))
+   (match_dup 5)]
+  "operands[4] = gen_label_rtx ();
+   operands[5] = gen_label_rtx ();")
+
+(define_split
+  [(parallel
+     [(set (match_operand 0 "register_operand" "")
+          (match_operator 2 "nshift_operator"
+            [(match_dup 0)
+             (match_operand:QI 1 "register_operand" "")]))
+      (clobber (match_operand:QI 3 "register_operand" ""))])]
+  "flow2_completed
+   && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
+  [(set (match_dup 3)
+       (match_dup 1))
+   (set (cc0)
+       (match_dup 3))
+   (set (pc)
+        (if_then_else (le (cc0) (const_int 0))
+                     (label_ref (match_dup 5))
+                     (pc)))
+   (match_dup 4)
+   (parallel
+     [(set (match_dup 0)
+          (match_op_dup 2 [(match_dup 0) (const_int 1)]))
+      (clobber (scratch:QI))])
+   (set (match_dup 3)
+       (plus:QI (match_dup 3) (const_int -1)))
+   (set (cc0)
+       (match_dup 3))
+   (set (pc)
+        (if_then_else (ne (cc0) (const_int 0))
+                     (label_ref (match_dup 4))
+                     (pc)))
+   (match_dup 5)]
+  "operands[4] = gen_label_rtx ();
+   operands[5] = gen_label_rtx ();")
 \f
 ;; ----------------------------------------------------------------------
 ;; ROTATIONS
 ;; Normal loads with a 32bit destination.
 ;;
 
-(define_insn ""
+(define_insn "*extzv_1_r_h8300"
   [(set (match_operand:SI 0 "register_operand" "=&r")
        (zero_extract:SI (match_operand:HI 1 "register_operand" "r")
                         (const_int 1)
    && INTVAL (operands[2]) < 16"
   "* return output_simode_bld (0, operands);"
   [(set_attr "cc" "clobber")
-   (set_attr "length" "6")])
+   (set_attr "length" "8")])
 
-(define_insn ""
+(define_insn "*extzv_1_r_h8300hs"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
                         (const_int 1)
    && INTVAL (operands[2]) < 16"
   "* return output_simode_bld (0, operands);"
   [(set_attr "cc" "clobber")
-   (set_attr "length" "6")])
+   (set_attr "length" "8")])
 
 ;;
 ;; Inverted loads with a 32bit destination.
 ;;
 
-(define_insn ""
+(define_insn "*extzv_1_r_inv_h8300"
   [(set (match_operand:SI 0 "register_operand" "=&r")
        (zero_extract:SI (xor:HI (match_operand:HI 1 "register_operand" "r")
                                 (match_operand:HI 3 "const_int_operand" "n"))
    && (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
   "* return output_simode_bld (1, operands);"
   [(set_attr "cc" "clobber")
-   (set_attr "length" "6")])
+   (set_attr "length" "8")])
 
-(define_insn ""
+(define_insn "*extzv_1_r_inv_h8300hs"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
                                 (match_operand 3 "const_int_operand" "n"))
    && (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
   "* return output_simode_bld (1, operands);"
   [(set_attr "cc" "clobber")
-   (set_attr "length" "6")])
+   (set_attr "length" "8")])
 
 (define_expand "insv"
   [(set (zero_extract:HI (match_operand:HI 0 "general_operand" "")
 ;; COMBINE PATTERNS
 ;; -----------------------------------------------------------------
 
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
-               (match_operand:HI 2 "register_operand" "0")))]
-  "REG_P (operands[0])
-   && REG_P (operands[1])
-   && REGNO (operands[0]) != REGNO (operands[1])"
-  "or\\t%X1,%s0"
-  [(set_attr "cc" "clobber")
-   (set_attr "length" "2")])
+;; extzv:SI
 
-(define_insn ""
+(define_insn "*extzv_8_8"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
-               (match_operand:SI 2 "register_operand" "0")))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && REG_P (operands[0])
-   && REG_P (operands[1])
-   && (REGNO (operands[0]) != REGNO (operands[1]))"
-  "or.w\\t%T1,%f0"
-  [(set_attr "cc" "clobber")
-   (set_attr "length" "2")])
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+                        (const_int 8)
+                        (const_int 8)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "mov.b\\t%x1,%w0\;extu.w\\t%f0\;extu.l\\t%S0"
+  [(set_attr "cc" "set_znv")
+   (set_attr "length" "6")])
 
-(define_insn ""
+(define_insn "*extzv_8_16"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
-               (match_operand:SI 2 "register_operand" "0")))]
-  "REG_P (operands[0])
-   && REG_P (operands[1])
-   && REGNO (operands[0]) != REGNO (operands[1])"
-  "or\\t%X1,%w0"
-  [(set_attr "cc" "clobber")
-   (set_attr "length" "2")])
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+                        (const_int 8)
+                        (const_int 16)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "mov.w\\t%e1,%f0\;extu.w\\t%f0\;extu.l\\t%S0"
+  [(set_attr "cc" "set_znv")
+   (set_attr "length" "6")])
 
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
-               (match_operand:HI 2 "register_operand" "0")))]
-  "REG_P (operands[0])
-   && REG_P (operands[1])
-   && REGNO (operands[0]) != REGNO (operands[1])"
-  "xor\\t%X1,%s0"
-  [(set_attr "cc" "clobber")
-   (set_attr "length" "2")])
+;; Extract the exponent of a float.
 
-(define_insn ""
+(define_insn_and_split "*extzv_8_23"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
-               (match_operand:SI 2 "register_operand" "0")))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && REG_P (operands[0])
-   && REG_P (operands[1])
-   && (REGNO (operands[0]) != REGNO (operands[1]))"
-  "xor.w\\t%T1,%f0"
-  [(set_attr "cc" "clobber")
-   (set_attr "length" "2")])
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "0")
+                        (const_int 8)
+                        (const_int 23)))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0)
+                  (ashift:SI (match_dup 0)
+                             (const_int 1)))
+             (clobber (scratch:QI))])
+   (parallel [(set (match_dup 0)
+                  (lshiftrt:SI (match_dup 0)
+                               (const_int 24)))
+             (clobber (scratch:QI))])]
+  "")
 
-(define_insn ""
+;; and:SI
+
+;; ((SImode) HImode) << 15
+
+(define_insn_and_split "*twoshifts_l16_r1"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
-               (match_operand:SI 2 "register_operand" "0")))]
-  "REG_P (operands[0])
-   && REG_P (operands[1])
-   && REGNO (operands[0]) != REGNO (operands[1])"
-  "xor\\t%X1,%w0"
+       (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
+                          (const_int 15))
+               (const_int 2147450880)))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0)
+                  (ashift:SI (match_dup 0)
+                             (const_int 16)))
+             (clobber (scratch:QI))])
+   (parallel [(set (match_dup 0)
+                  (lshiftrt:SI (match_dup 0)
+                               (const_int 1)))
+             (clobber (scratch:QI))])]
+  "")
+
+;; Transform (SImode << B) & 0xffff into (SImode) (HImode << B).
+
+(define_insn_and_split "*andsi3_ashift_n_lower"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+                          (match_operand:QI 2 "const_int_operand" "S,n"))
+               (match_operand:SI 3 "const_int_operand" "n,n")))
+   (clobber (match_scratch:QI 4 "=X,&r"))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && INTVAL (operands[2]) <= 15
+   && INTVAL (operands[3]) == ((-1 << INTVAL (operands[2])) & 0xffff)"
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 5)
+                  (ashift:HI (match_dup 5)
+                             (match_dup 2)))
+             (clobber (match_dup 4))])
+   (set (match_dup 0)
+       (zero_extend:SI (match_dup 5)))]
+  "operands[5] = gen_rtx_REG (HImode, REGNO (operands[0]));")
+
+;; Accept (A >> 30) & 2 and the like.
+
+(define_insn "*andsi3_lshiftrt_n_sb"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                            (match_operand:SI 2 "const_int_operand" "n"))
+               (match_operand:SI 3 "single_one_operand" "n")))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && exact_log2 (INTVAL (operands[3])) < 16
+   && INTVAL (operands[2]) + exact_log2 (INTVAL (operands[3])) == 31"
+  "*
+{
+  operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
+  return \"shll.l\\t%S0\;xor.l\\t%S0,%S0\;bst\\t%Z3,%Y0\";
+}"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn_and_split "*andsi3_lshiftrt_9_sb"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                            (const_int 9))
+               (const_int 4194304)))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0)
+       (and:SI (lshiftrt:SI (match_dup 0)
+                            (const_int 25))
+               (const_int 64)))
+   (parallel [(set (match_dup 0)
+                  (ashift:SI (match_dup 0)
+                             (const_int 16)))
+             (clobber (scratch:QI))])]
+  "")
+
+;; plus:SI
+
+(define_insn "*addsi3_upper"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+                         (const_int 65536))
+                (match_operand:SI 2 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "add.w\\t%f1,%e0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*addsi3_lshiftrt_16_zexthi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                             (const_int 16))
+                (zero_extend:SI (match_operand:HI 2 "register_operand" "0"))))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "add.w\\t%e1,%f0\;xor.w\\t%e0,%e0\;rotxl.w\\t%e0,%e0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "6")])
+
+;; ior:HI
+
+(define_insn "*iorhi3_zext"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+               (match_operand:HI 2 "register_operand" "0")))]
+  ""
+  "or\\t%X1,%s0"
   [(set_attr "cc" "clobber")
    (set_attr "length" "2")])
 
-(define_insn ""
+(define_insn "*iorhi3_ashift_8"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (ior:HI (ashift:HI (match_operand:HI 1 "register_operand" "r")
+                          (const_int 8))
+               (match_operand:HI 2 "register_operand" "0")))]
+  ""
+  "or.b\\t%s1,%t0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*iorhi3_lshiftrt_8"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (ior:HI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
+                            (const_int 8))
+               (match_operand:HI 2 "register_operand" "0")))]
+  ""
+  "or.b\\t%t1,%s0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*iorhi3_two_qi"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
                (ashift:HI (match_operand:HI 2 "register_operand" "r")
                           (const_int 8))))]
-  "REG_P (operands[0])
-   && REG_P (operands[2])
-   && REGNO (operands[0]) != REGNO (operands[2])"
+  ""
   "mov.b\\t%s2,%t0"
   [(set_attr "cc" "clobber")
    (set_attr "length" "2")])
 
-(define_insn ""
+;; ior:SI
+
+(define_insn "*iorsi3_zexthi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+               (match_operand:SI 2 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "or.w\\t%T1,%f0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*iorsi3_zextqi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
+               (match_operand:SI 2 "register_operand" "0")))]
+  ""
+  "or\\t%X1,%w0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*iorsi3_ashift_16"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+                          (const_int 16))
+               (match_operand:SI 2 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "or.w\\t%f1,%e0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*iorsi3_two_hi"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
                (ashift:SI (match_operand:SI 2 "register_operand" "r")
                           (const_int 16))))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && REG_P (operands[0])
-   && REG_P (operands[2])
-   && (REGNO (operands[0]) != REGNO (operands[2]))"
+  "TARGET_H8300H || TARGET_H8300S"
   "mov.w\\t%f2,%e0"
   [(set_attr "cc" "clobber")
    (set_attr "length" "2")])
 
+(define_insn_and_split "*iorsi3_two_qi_sext"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "0"))
+               (ashift:SI (sign_extend:SI (match_operand:QI 2 "register_operand" "r"))
+                          (const_int 8))))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 3)
+       (ior:HI (zero_extend:HI (match_dup 1))
+               (ashift:HI (match_dup 4)
+                          (const_int 8))))
+   (set (match_dup 0)
+       (sign_extend:SI (match_dup 3)))]
+  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
+   operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));")
+
+(define_insn "*iorsi3_w"
+  [(set (match_operand:SI 0 "register_operand" "=r,&r")
+       (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0,0")
+                       (const_int -256))
+               (zero_extend:SI (match_operand:QI 2 "general_operand_src" "r,g>"))))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "mov.b\\t%X2,%w0"
+  [(set_attr "length" "2,8")
+   (set_attr "cc" "clobber,clobber")])
+
+(define_insn "*iorsi3_ashift_31"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+                          (const_int 31))
+               (match_operand:SI 2 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "rotxl.l\\t%S0\;bor\\t#0,%w1\;rotxr.l\\t%S0"
+  [(set_attr "length" "6")
+   (set_attr "cc" "set_znv")])
+
+(define_insn "*iorsi3_and_lshiftrt_n_sb"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                                    (const_int 30))
+                       (const_int 2))
+               (match_operand:SI 2 "register_operand" "0")))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "rotl.l\\t%S1\;rotr.l\\t%S1\;bor\\t#1,%w0\;bst\\t#1,%w0"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*iorsi3_and_lshiftrt_9_sb"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                                    (const_int 9))
+                       (const_int 4194304))
+               (match_operand:SI 2 "register_operand" "0")))
+   (clobber (match_scratch:HI 3 "=&r"))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "*
+{
+  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+    return \"shll.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0\";
+  else
+    return \"rotl.l\\t%S1\;rotr.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0\";
+}"
+  [(set_attr "length" "10")
+   (set_attr "cc" "clobber")])
+
+;; Used to OR the exponent of a float.
+
+(define_insn "*iorsi3_shift"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+                          (const_int 23))
+               (match_operand:SI 2 "register_operand" "0")))
+   (clobber (match_scratch:SI 3 "=&r"))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "#")
+
+(define_split
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+                            (const_int 23))
+                 (match_dup 0)))
+     (clobber (match_operand:SI 2 "register_operand" ""))])]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && flow2_completed
+   && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
+   && REGNO (operands[0]) != REGNO (operands[1])"
+  [(parallel [(set (match_dup 3)
+                  (ashift:HI (match_dup 3)
+                             (const_int 7)))
+             (clobber (scratch:QI))])
+   (set (match_dup 0)
+       (ior:SI (ashift:SI (match_dup 1)
+                          (const_int 16))
+               (match_dup 0)))]
+  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));")
+
+(define_split
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+                            (const_int 23))
+                 (match_dup 0)))
+     (clobber (match_operand:SI 2 "register_operand" ""))])]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && flow2_completed
+   && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
+        && REGNO (operands[0]) != REGNO (operands[1]))"
+  [(set (match_dup 2)
+       (match_dup 1))
+   (parallel [(set (match_dup 3)
+                  (ashift:HI (match_dup 3)
+                             (const_int 7)))
+             (clobber (scratch:QI))])
+   (set (match_dup 0)
+       (ior:SI (ashift:SI (match_dup 2)
+                          (const_int 16))
+               (match_dup 0)))]
+  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[2]));")
+
+(define_insn "*iorsi2_and_1_lshiftrt_1"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
+                       (const_int 1))
+               (lshiftrt:SI (match_dup 1)
+                            (const_int 1))))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "shlr.l\\t%S0\;bor\\t#0,%w0\;bst\\t#0,%w0"
+  [(set_attr "length" "6")
+   (set_attr "cc" "clobber")])
+
+;; Used to add the exponent of a float.
+
+(define_insn "*addsi3_shift"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+                         (const_int 8388608))
+                (match_operand:SI 2 "register_operand" "0")))
+   (clobber (match_scratch:SI 3 "=&r"))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "#")
+
+(define_split
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                           (const_int 8388608))
+                  (match_dup 0)))
+     (clobber (match_operand:SI 2 "register_operand" ""))])]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && flow2_completed
+   && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
+   && REGNO (operands[0]) != REGNO (operands[1])"
+  [(parallel [(set (match_dup 3)
+                  (ashift:HI (match_dup 3)
+                             (const_int 7)))
+             (clobber (scratch:QI))])
+   (set (match_dup 0)
+       (plus:SI (mult:SI (match_dup 1)
+                         (const_int 65536))
+                (match_dup 0)))]
+  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));")
+
+(define_split
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                           (const_int 8388608))
+                  (match_dup 0)))
+     (clobber (match_operand:SI 2 "register_operand" ""))])]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && flow2_completed
+   && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
+        && REGNO (operands[0]) != REGNO (operands[1]))"
+  [(set (match_dup 2)
+       (match_dup 1))
+   (parallel [(set (match_dup 3)
+                  (ashift:HI (match_dup 3)
+                             (const_int 7)))
+             (clobber (scratch:QI))])
+   (set (match_dup 0)
+       (plus:SI (mult:SI (match_dup 2)
+                         (const_int 65536))
+                (match_dup 0)))]
+  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[2]));")
+
+;; xor:HI
+
+(define_insn "*xorhi3_zextqi"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+               (match_operand:HI 2 "register_operand" "0")))]
+  ""
+  "xor\\t%X1,%s0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+;; xor:SI
+
+(define_insn "*xorsi3_zexthi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+               (match_operand:SI 2 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "xor.w\\t%T1,%f0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+(define_insn "*xorsi3_zextqi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
+               (match_operand:SI 2 "register_operand" "0")))]
+  ""
+  "xor\\t%X1,%w0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+;; ashift:SI
+
+(define_insn_and_split "*ashiftsi_sextqi_7"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ashift:SI (sign_extend:SI (match_operand:QI 1 "register_operand" "0"))
+                  (const_int 7)))]
+  "(TARGET_H8300H || TARGET_H8300S)"
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 2)
+                  (ashift:HI (match_dup 2)
+                             (const_int 8)))
+             (clobber (scratch:QI))])
+   (set (match_dup 0)
+       (sign_extend:SI (match_dup 2)))
+   (parallel [(set (match_dup 0)
+                  (ashiftrt:SI (match_dup 0)
+                               (const_int 1)))
+             (clobber (scratch:QI))])]
+  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
+
 ;; Storing a part of HImode to QImode.
 
 (define_insn ""
   "TARGET_H8300H || TARGET_H8300S"
   "mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0"
   [(set_attr "cc" "set_znv")
-   (set_attr "length" "8")])
+   (set_attr "length" "10")])
 
 (define_insn ""
   [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
   "TARGET_H8300H || TARGET_H8300S"
   "mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0"
   [(set_attr "cc" "set_znv")
-   (set_attr "length" "8")])
+   (set_attr "length" "10")])
 
 (define_insn_and_split ""
   [(set (pc)
                      (label_ref (match_dup 1))
                      (pc)))]
   "")
+\f
+;; -----------------------------------------------------------------
+;; PEEPHOLE PATTERNS
+;; -----------------------------------------------------------------
+
+;; Convert (A >> B) & C to (A & 255) >> B if C == 255 >> B.
+
+(define_peephole2
+  [(parallel
+     [(set (match_operand:HI 0 "register_operand" "")
+          (lshiftrt:HI (match_dup 0)
+                       (match_operand:HI 1 "const_int_operand" "")))
+      (clobber (match_operand:HI 2 "" ""))])
+   (set (match_dup 0)
+       (and:HI (match_dup 0)
+               (match_operand:HI 3 "const_int_operand" "")))]
+  "INTVAL (operands[3]) == (255 >> INTVAL (operands[1]))"
+  [(set (match_dup 0)
+       (and:HI (match_dup 0)
+               (const_int 255)))
+   (parallel
+     [(set (match_dup 0)
+          (lshiftrt:HI (match_dup 0)
+                       (match_dup 1)))
+      (clobber (match_dup 2))])]
+  "")
+
+;; Convert (A << B) & C to (A & 255) << B if C == 255 << B.
+
+(define_peephole2
+  [(parallel
+     [(set (match_operand:HI 0 "register_operand" "")
+          (ashift:HI (match_dup 0)
+                     (match_operand:HI 1 "const_int_operand" "")))
+      (clobber (match_operand:HI 2 "" ""))])
+   (set (match_dup 0)
+       (and:HI (match_dup 0)
+               (match_operand:HI 3 "const_int_operand" "")))]
+  "INTVAL (operands[3]) == (255 << INTVAL (operands[1]))"
+  [(set (match_dup 0)
+       (and:HI (match_dup 0)
+               (const_int 255)))
+   (parallel
+     [(set (match_dup 0)
+          (ashift:HI (match_dup 0)
+                     (match_dup 1)))
+      (clobber (match_dup 2))])]
+  "")
+
+;; Convert (A >> B) & C to (A & 255) >> B if C == 255 >> B.
+
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand" "")
+          (lshiftrt:SI (match_dup 0)
+                       (match_operand:SI 1 "const_int_operand" "")))
+      (clobber (match_operand:SI 2 "" ""))])
+   (set (match_dup 0)
+       (and:SI (match_dup 0)
+               (match_operand:SI 3 "const_int_operand" "")))]
+  "INTVAL (operands[3]) == (255 >> INTVAL (operands[1]))"
+  [(set (match_dup 0)
+       (and:SI (match_dup 0)
+               (const_int 255)))
+   (parallel
+     [(set (match_dup 0)
+          (lshiftrt:SI (match_dup 0)
+                       (match_dup 1)))
+      (clobber (match_dup 2))])]
+  "")
+
+;; Convert (A << B) & C to (A & 255) << B if C == 255 << B.
+
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand" "")
+          (ashift:SI (match_dup 0)
+                     (match_operand:SI 1 "const_int_operand" "")))
+      (clobber (match_operand:SI 2 "" ""))])
+   (set (match_dup 0)
+       (and:SI (match_dup 0)
+               (match_operand:SI 3 "const_int_operand" "")))]
+  "INTVAL (operands[3]) == (255 << INTVAL (operands[1]))"
+  [(set (match_dup 0)
+       (and:SI (match_dup 0)
+               (const_int 255)))
+   (parallel
+     [(set (match_dup 0)
+          (ashift:SI (match_dup 0)
+                     (match_dup 1)))
+      (clobber (match_dup 2))])]
+  "")
+
+;; Convert (A >> B) & C to (A & 65535) >> B if C == 65535 >> B.
+
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand" "")
+          (lshiftrt:SI (match_dup 0)
+                       (match_operand:SI 1 "const_int_operand" "")))
+      (clobber (match_operand:SI 2 "" ""))])
+   (set (match_dup 0)
+       (and:SI (match_dup 0)
+               (match_operand:SI 3 "const_int_operand" "")))]
+  "INTVAL (operands[3]) == (65535 >> INTVAL (operands[1]))"
+  [(set (match_dup 0)
+       (and:SI (match_dup 0)
+               (const_int 65535)))
+   (parallel
+     [(set (match_dup 0)
+          (lshiftrt:SI (match_dup 0)
+                       (match_dup 1)))
+      (clobber (match_dup 2))])]
+  "")
+
+;; Convert (A << B) & C to (A & 65535) << B if C == 65535 << B.
+
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand" "")
+          (ashift:SI (match_dup 0)
+                     (match_operand:SI 1 "const_int_operand" "")))
+      (clobber (match_operand:SI 2 "" ""))])
+   (set (match_dup 0)
+       (and:SI (match_dup 0)
+               (match_operand:SI 3 "const_int_operand" "")))]
+  "INTVAL (operands[3]) == (65535 << INTVAL (operands[1]))"
+  [(set (match_dup 0)
+       (and:SI (match_dup 0)
+               (const_int 65535)))
+   (parallel
+     [(set (match_dup 0)
+          (ashift:SI (match_dup 0)
+                     (match_dup 1)))
+      (clobber (match_dup 2))])]
+  "")
+
+;; Convert a QImode push into an SImode push so that the
+;; define_peephole2 below can cram multiple pushes into one stm.l.
+
+(define_peephole2
+  [(parallel [(set (reg:SI SP_REG)
+                   (plus:SI (reg:SI SP_REG) (const_int -4)))
+              (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
+                   (match_operand:QI 0 "register_operand" ""))])]
+  "TARGET_H8300S"
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_dup 0))]
+  "operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));")
+
+;; Convert a HImode push into an SImode push so that the
+;; define_peephole2 below can cram multiple pushes into one stm.l.
+
+(define_peephole2
+  [(parallel [(set (reg:SI SP_REG)
+                   (plus:SI (reg:SI SP_REG) (const_int -4)))
+              (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
+                   (match_operand:HI 0 "register_operand" ""))])]
+  "TARGET_H8300S"
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_dup 0))]
+  "operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));")
+
+;; Cram four pushes into stm.l.
+
+(define_peephole2
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 0 "register_operand" ""))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 1 "register_operand" ""))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 2 "register_operand" ""))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 3 "register_operand" ""))]
+  "TARGET_H8300S
+   && REGNO (operands[0]) == 0
+   && REGNO (operands[1]) == 1
+   && REGNO (operands[2]) == 2
+   && REGNO (operands[3]) == 3"
+  [(parallel [(set (reg:SI SP_REG)
+                  (plus:SI (reg:SI SP_REG)
+                           (const_int -16)))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+                  (match_dup 0))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+                  (match_dup 1))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+                  (match_dup 2))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -16)))
+                  (match_dup 3))])]
+  "")
+
+;; Cram three pushes into stm.l.
+
+(define_peephole2
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 0 "register_operand" ""))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 1 "register_operand" ""))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 2 "register_operand" ""))]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0
+       && REGNO (operands[1]) == 1
+       && REGNO (operands[2]) == 2)
+       || (REGNO (operands[0]) == 4
+          && REGNO (operands[1]) == 5
+          && REGNO (operands[2]) == 6))"
+  [(parallel [(set (reg:SI SP_REG)
+                  (plus:SI (reg:SI SP_REG)
+                           (const_int -12)))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+                  (match_dup 0))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+                  (match_dup 1))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+                  (match_dup 2))])]
+  "")
+
+;; Cram two pushes into stm.l.
+
+(define_peephole2
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 0 "register_operand" ""))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+       (match_operand:SI 1 "register_operand" ""))]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+       || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+       || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+  [(parallel [(set (reg:SI SP_REG)
+                  (plus:SI (reg:SI SP_REG)
+                           (const_int -8)))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+                  (match_dup 0))
+             (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+                  (match_dup 1))])]
+  "")
+
+;; Turn
+;;
+;;   mov.w #2,r0
+;;   add.w r7,r0  (6 bytes)
+;;
+;; into
+;;
+;;   mov.w r7,r0
+;;   adds  #2,r0  (4 bytes)
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+       (match_operand:HI 1 "const_int_operand" ""))
+   (set (match_dup 0)
+       (plus:HI (match_dup 0)
+                (match_operand:HI 2 "register_operand" "")))]
+  "REG_P (operands[0]) && REG_P (operands[2])
+   && REGNO (operands[0]) != REGNO (operands[2])
+   && (CONST_OK_FOR_J (INTVAL (operands[1]))
+       || CONST_OK_FOR_L (INTVAL (operands[1]))
+       || CONST_OK_FOR_N (INTVAL (operands[1])))"
+  [(set (match_dup 0)
+       (match_dup 2))
+   (set (match_dup 0)
+       (plus:HI (match_dup 0)
+                (match_dup 1)))]
+  "")
+
+;; Turn
+;;
+;;   sub.l  er0,er0
+;;   add.b  #4,r0l
+;;   add.l  er7,er0  (6 bytes)
+;;
+;; into
+;;
+;;   mov.l  er7,er0
+;;   adds   #4,er0   (4 bytes)
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "const_int_operand" ""))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0)
+                (match_operand:SI 2 "register_operand" "")))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && REG_P (operands[0]) && REG_P (operands[2])
+   && REGNO (operands[0]) != REGNO (operands[2])
+   && (CONST_OK_FOR_L (INTVAL (operands[1]))
+       || CONST_OK_FOR_N (INTVAL (operands[1])))"
+  [(set (match_dup 0)
+       (match_dup 2))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0)
+                (match_dup 1)))]
+  "")
+
+;; Turn
+;;
+;;   mov.l er7,er0
+;;   add.l #10,er0  (takes 8 bytes)
+;;
+;; into
+;;
+;;   sub.l er0,er0
+;;   add.b #10,r0l
+;;   add.l er7,er0  (takes 6 bytes)
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "register_operand" ""))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0)
+                (match_operand:SI 2 "const_int_operand" "")))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && REG_P (operands[0]) && REG_P (operands[1])
+   && REGNO (operands[0]) != REGNO (operands[1])
+   && !CONST_OK_FOR_L (INTVAL (operands[2]))
+   && !CONST_OK_FOR_N (INTVAL (operands[2]))
+   && ((INTVAL (operands[2]) & 0xff) == INTVAL (operands[2])
+       || (INTVAL (operands[2]) & 0xff00) == INTVAL (operands[2])
+       || INTVAL (operands[2]) == 0xffff
+       || INTVAL (operands[2]) == 0xfffe)"
+  [(set (match_dup 0)
+       (match_dup 2))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0)
+                (match_dup 1)))]
+  "")
+
+;; Turn
+;;
+;;   subs   #1,er4
+;;   mov.w  r4,r4
+;;   bne    .L2028
+;;
+;; into
+;;
+;;   dec.w  #1,r4
+;;   bne    .L2028
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand 1 "incdec_operand" "")))
+   (set (cc0)
+       (match_dup 0))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(set (match_operand:HI 0 "register_operand" "")
+       (unspec:HI [(match_dup 0)
+                   (match_dup 1)]
+                  UNSPEC_INCDEC))
+   (set (cc0)
+       (match_dup 0))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "")
+
+;; The SImode version of the previous pattern.
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_dup 0)
+                (match_operand 1 "incdec_operand" "")))
+   (set (cc0)
+       (match_dup 0))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (unspec:SI [(match_dup 0)
+                   (match_dup 1)]
+                  UNSPEC_INCDEC))
+   (set (cc0)
+       (match_dup 0))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "")
+
+;; (compare (reg:SI) (const_int)) takes 6 bytes, so we try to achieve
+;; the equivalent with shorter sequences.  Here is the summary.  Cases
+;; are grouped for each define_peephole2.
+;;
+;; reg  const_int                   use     insn
+;; --------------------------------------------------------
+;; live    -2                       eq/ne   copy and inc.l
+;; live    -1                       eq/ne   copy and inc.l
+;; live     1                       eq/ne   copy and dec.l
+;; live     2                       eq/ne   copy and dec.l
+;;
+;; dead    -2                       eq/ne   inc.l
+;; dead    -1                       eq/ne   inc.l
+;; dead     1                       eq/ne   dec.l
+;; dead     2                       eq/ne   dec.l
+;;
+;; dead 0x000000?? except 1 and 2   eq/ne   xor.b and test
+;; dead 0x0000??00                  eq/ne   xor.b and test
+;; dead 0x0000ffff                  eq/ne   not.w and test
+;; dead 0xffff0000                  eq/ne   not.w and test
+;;
+;; dead 0xffffff?? except -1 and -2 eq/ne   xor.b and not.l
+;; dead 0xffff??ff                  eq/ne   xor.b and not.l
+;;
+;; dead     1                       geu/ltu and.b and test
+;; dead     3                       geu/ltu and.b and test
+;; dead     7                       geu/ltu and.b and test
+;; dead    15                       geu/ltu and.b and test
+;; dead    31                       geu/ltu and.b and test
+;; dead    63                       geu/ltu and.b and test
+;; dead   127                       geu/ltu and.b and test
+;; dead   255                       geu/ltu and.b and test
+;;
+;; dead 65535                       geu/ltu mov.w
+
+;; For a small constant, it is cheaper to actually do the subtraction
+;; and then test the register.
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:HI 0 "register_operand" "")
+                (match_operand:HI 1 "incdec_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && 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 (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = GEN_INT (- INTVAL (operands[1]));")
+
+;; The SImode version of the previous pattern.
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "")
+                (match_operand:SI 1 "incdec_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && 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 (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = GEN_INT (- INTVAL (operands[1]));")
+
+;; For certain (in)equaltity comparisions against a constant, we can
+;; XOR the register with the constant, and test the register against
+;; 0.
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "")
+                (match_operand:SI 1 "const_int_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && peep2_reg_dead_p (1, operands[0])
+   && ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1])
+       || (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1])
+       || INTVAL (operands[1]) == 0x0000ffff
+       || INTVAL (operands[1]) == 0xffff0000)
+   && 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 (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "")
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "")
+                (match_operand:SI 1 "const_int_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && peep2_reg_dead_p (1, operands[0])
+   && ((INTVAL (operands[1]) | 0x00ff) == -1
+       || (INTVAL (operands[1]) | 0xff00) == -1)
+   && INTVAL (operands[1]) != -1
+   && INTVAL (operands[1]) != -2"
+  [(set (match_dup 0)
+       (xor:SI (match_dup 0)
+               (match_dup 4)))
+   (set (match_dup 0)
+       (not:SI (match_dup 0)))
+   (set (cc0)
+       (match_dup 0))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = GEN_INT (INTVAL (operands[1]) ^ -1);")
+
+;; Transform A <= 1 to (A & 0xfffffffe) == 0.
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "")
+                (match_operand:SI 1 "const_int_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 2 "gtuleu_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && peep2_reg_dead_p (1, operands[0])
+   && (INTVAL (operands[1]) == 1
+       || INTVAL (operands[1]) == 3
+       || INTVAL (operands[1]) == 7
+       || INTVAL (operands[1]) == 15
+       || INTVAL (operands[1]) == 31
+       || INTVAL (operands[1]) == 63
+       || INTVAL (operands[1]) == 127
+       || INTVAL (operands[1]) == 255)"
+  [(set (match_dup 0)
+       (and:SI (match_dup 0)
+               (match_dup 5)))
+   (set (cc0)
+       (match_dup 0))
+   (set (pc)
+       (if_then_else (match_dup 4)
+                     (label_ref (match_dup 3))
+                     (pc)))]
+  "operands[4] = ((GET_CODE (operands[2]) == GTU) ?
+                 gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx) :
+                 gen_rtx_EQ (VOIDmode, cc0_rtx, const0_rtx));
+   operands[5] = GEN_INT (~INTVAL (operands[1]));")
+
+;; Transform A <= 255 to (A & 0xff00) == 0.
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:HI 0 "register_operand" "")
+                (const_int 255)))
+   (set (pc)
+       (if_then_else (match_operator 1 "gtuleu_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(set (cc0)
+       (and:HI (match_dup 0)
+               (const_int -256)))
+   (set (pc)
+       (if_then_else (match_dup 4)
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = ((GET_CODE (operands[1]) == GTU) ?
+                 gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx) :
+                 gen_rtx_EQ (VOIDmode, cc0_rtx, const0_rtx));")
+
+;; Transform A <= 65535 to (A & 0xffff0000) == 0.
+
+(define_peephole2
+  [(set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "")
+                (const_int 65535)))
+   (set (pc)
+       (if_then_else (match_operator 1 "gtuleu_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(set (cc0)
+       (and:SI (match_dup 0)
+               (const_int -65536)))
+   (set (pc)
+       (if_then_else (match_dup 4)
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = ((GET_CODE (operands[1]) == GTU) ?
+                 gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx) :
+                 gen_rtx_EQ (VOIDmode, cc0_rtx, const0_rtx));")
+
+;; For constants like -1, -2, 1, 2, it is still cheaper to make a copy
+;; of the register being tested, do the subtraction on the copy, and
+;; then test the copy.  We avoid this transformation if we see more
+;; than one copy of the same compare insn.
+
+(define_peephole2
+  [(match_scratch:SI 4 "r")
+   (set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "")
+                (match_operand:SI 1 "incdec_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && !peep2_reg_dead_p (1, operands[0])
+   && !rtx_equal_p (PATTERN (insn),
+                   PATTERN (next_nonnote_insn (next_nonnote_insn (insn))))"
+  [(set (match_dup 4)
+       (match_dup 0))
+   (set (match_dup 4)
+       (unspec:SI [(match_dup 4)
+                   (match_dup 5)]
+                  UNSPEC_INCDEC))
+   (set (cc0)
+       (match_dup 4))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[5] = GEN_INT (- INTVAL (operands[1]));")
+
+;; Narrow the mode of testing if possible.
+
+(define_peephole2
+  [(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 (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 4)
+       (and:QI (match_dup 4)
+               (match_dup 5)))
+   (set (cc0)
+       (match_dup 4))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = gen_rtx_REG (QImode, REGNO (operands[0]));
+   operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode));")
+
+(define_peephole2
+  [(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 (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 4)
+       (and:QI (match_dup 4)
+               (match_dup 5)))
+   (set (cc0)
+       (match_dup 4))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = gen_rtx_REG (QImode, REGNO (operands[0]));
+   operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode));")
+
+(define_peephole2
+  [(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 (pc)
+       (if_then_else (match_operator 3 "eqne_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 4)
+       (and:HI (match_dup 4)
+               (match_dup 5)))
+   (set (cc0)
+       (match_dup 4))
+   (set (pc)
+       (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+                     (label_ref (match_dup 2))
+                     (pc)))]
+  "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
+   operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), HImode));")