]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/mn10300/mn10300.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / mn10300 / mn10300.md
index e8d2ae1194dc829821558e53e436f3b14074536d..e1a016bb9e98124f688a5446a89e24faa1c08cf2 100644 (file)
@@ -1,7 +1,5 @@
 ;; GCC machine description for Matsushita MN10300
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1996-2020 Free Software Foundation, Inc.
 ;; Contributed by Jeff Law (law@cygnus.com).
 
 ;; This file is part of GCC.
@@ -42,6 +40,8 @@
 
   ;; This is used to encode LIW patterns.
   (UNSPEC_LIW          8)
+  ;; This is for the low overhead loop instructions.
+  (UNSPEC_SETLB         9)
 ])
 
 (include "predicates.md")
          (const_int 1)
 
          (and (eq_attr "isa" "am33")
-             (ne (symbol_ref "TARGET_AM33") (const_int 0)))
+             (match_test "TARGET_AM33"))
          (const_int 1)
 
          (and (eq_attr "isa" "am33_2")
-             (ne (symbol_ref "TARGET_AM33_2") (const_int 0)))
+             (match_test "TARGET_AM33_2"))
          (const_int 1)
         
          (and (eq_attr "isa" "am34")
-             (ne (symbol_ref "TARGET_AM34") (const_int 0)))
+             (match_test "TARGET_AM34"))
          (const_int 1)
        ]
        (const_int 0))
 })
 
 (define_insn "*movqi_internal"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
-       (match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m,*z,d")
+       (match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D,d,*z"))]
   "(register_operand (operands[0], QImode)
     || register_operand (operands[1], QImode))"
 {
       return "";
     case 1:
     case 2:
+    case 5:
+    case 6:
       return "mov %1,%0";
     case 3:
     case 4:
                        (const_int 13) (const_int 24))
          (if_then_else (eq_attr "cpu" "am34")
                        (const_int 11) (const_int 22))
+         (const_int 11)
+         (const_int 11)
         ])]
 )
 
 })
 
 (define_insn "*movhi_internal"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
-       (match_operand:HI 1 "general_operand"      "  0,  i,D*r,m,D"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m,*z,d")
+       (match_operand:HI 1 "general_operand"      "  0,  i,D*r,m,D,d,*z"))]
   "(register_operand (operands[0], HImode)
     || register_operand (operands[1], HImode))"
 {
          && REGNO_EXTENDED_P (REGNO (operands[0]), 1))
        return "movu %1,%0";
       /* FALLTHRU */
+    case 5:
+    case 6:
     case 2:
       return "mov %1,%0";
     case 3:
                        (const_int 13) (const_int 24))
          (if_then_else (eq_attr "cpu" "am34")
                        (const_int 11) (const_int 22))
+         (if_then_else (eq_attr "cpu" "am34")
+                       (const_int 11) (const_int 22))
+         (if_then_else (eq_attr "cpu" "am34")
+                       (const_int 11) (const_int 22))
         ])]
 )
 
 
 (define_insn "*movsi_internal"
   [(set (match_operand:SI 0 "nonimmediate_operand"
-                         "=r,r,r,m,r, A,*y,*y,*z,*d")
+                         "=r,r,r,r,m,r, A,*y,*y,*z,*d")
        (match_operand:SI 1 "general_operand"
-                         " 0,i,r,r,m,*y, A, i,*d,*z"))]
+                         " 0,O,i,r,r,m,*y, A, i,*d,*z"))]
   "register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode)"
 {
     {
     case 0:
       return "";
-    case 1: /* imm-reg*/
+    case 1: /* imm-reg.  */
+    case 2: 
       /* See movhi for a discussion of sizes for 8-bit movu.  Note that the
         24-bit movu is 6 bytes, which is the same size as the full 32-bit
         mov form for An and Dn.  So again movu is only a win for Rn.  */
            return "movu %1,%0";
        }
       /* FALLTHRU */
-    case 2:  /* reg-reg */
-    case 3:  /* reg-mem */
-    case 4:  /* mem-reg */
-    case 5:  /* sp-reg */
-    case 6:  /* reg-sp */
-    case 7:  /* imm-sp */
-    case 8:  /* reg-mdr */
-    case 9:  /* mdr-reg */
+    case 3:  /* reg-reg */
+    case 4:  /* reg-mem */
+    case 5:  /* mem-reg */
+    case 6:  /* sp-reg */
+    case 7:  /* reg-sp */
+    case 8:  /* imm-sp */
+    case 9:  /* reg-mdr */
+    case 10:  /* mdr-reg */
       return "mov %1,%0";
     default:
       gcc_unreachable ();
     }
 }
-  [(set_attr "isa" "*,*,*,*,*,*,*,am33,*,*")
-   (set_attr "liw" "*,*,either,*,*,*,*,*,*,*")
+  [(set_attr "isa" "*,*,*,*,*,*,*,*,am33,*,*")
+   (set_attr "liw" "*,either,*,either,*,*,*,*,*,*,*")
    (set_attr "liw_op" "mov")
    (set_attr_alternative "timings"
         [(const_int 11)
+         (const_int 22)
          (const_int 22)
          (const_int 11)
          (if_then_else (eq_attr "cpu" "am34")
 })
 
 (define_insn "*movsf_internal"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q")
-       (match_operand:SF 1 "general_operand"      "  0,F,F,r,f,f,r,m,r,Q,f"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q,z,d")
+       (match_operand:SF 1 "general_operand"      "  0,F,F,r,f,f,r,m,r,Q,f,d,z"))]
   "TARGET_AM33_2
    && (register_operand (operands[0], SFmode)
        || register_operand (operands[1], SFmode))"
     case 3:
     case 7:
     case 8:
+    case 11:
+    case 12:
       return "mov %1,%0";
     case 2:
     case 4:
                                (const_int 13) (const_int 24))
                  (if_then_else (eq_attr "cpu" "am34")
                                (const_int 13) (const_int 24))
+                 (const_int 22)
+                 (const_int 22)
                 ])]
 )
 
 ;; ----------------------------------------------------------------------
 
 (define_insn "addsi3"
-  [(set (match_operand:SI          0 "register_operand"  "=r,r,!*y,!r")
-       (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,  0, r")
-                (match_operand:SI 2 "nonmemory_operand"  "r,i,  i, r")))
+  [(set (match_operand:SI          0 "register_operand"  "=r,r,r,!*y,!r")
+       (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,  0, r")
+                (match_operand:SI 2 "nonmemory_operand"  "r,O,i,  i, r")))
    (clobber (reg:CC CC_REG))]
   ""
   { return mn10300_output_add (operands, false); }
-  [(set_attr "timings" "11,11,11,22")
-   (set_attr "liw" "either,*,*,*")
+  [(set_attr "timings" "11,11,11,11,22")
+   (set_attr "liw" "either,either,*,*,*")
    (set_attr "liw_op" "add")]
 )
 
 ;; Note that ADD IMM,SP does not set the flags, so omit that here.
 (define_insn "*addsi3_flags"
-  [(set (match_operand:SI          0 "register_operand"  "=r,!r")
-       (plus:SI (match_operand:SI 1 "register_operand"  "%0, r")
-                (match_operand:SI 2 "nonmemory_operand" "ri, r")))
-   (set (reg CC_REG)
-       (compare (plus:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (plus:SI (match_operand:SI 1 "register_operand"  "%0, r")
+                         (match_operand:SI 2 "nonmemory_operand" "ri, r"))
+                (const_int 0)))
+   (set (match_operand:SI          0 "register_operand"  "=r,!r")
+       (plus:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
   { return mn10300_output_add (operands, true); }
   [(set_attr "timings" "11,22")]
 
 ;; A helper to expand the above, with the CC_MODE filled in.
 (define_expand "addsi3_flags"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (plus:SI (match_operand:SI 1 "register_operand")
-                           (match_operand:SI 2 "nonmemory_operand")))
-             (set (reg:CCZNC CC_REG)
+  [(parallel [(set (reg:CCZNC CC_REG)
                   (compare:CCZNC (plus:SI (match_dup 1) (match_dup 2))
-                                 (const_int 0)))])]
+                                 (const_int 0)))
+             (set (match_operand:SI 0 "register_operand")
+                  (plus:SI (match_operand:SI 1 "register_operand")
+                           (match_operand:SI 2 "nonmemory_operand")))])]
   ""
 )
 
   rtx scratch = NULL_RTX;
   if (!rtx_equal_p (operands[0], operands[2]))
     {
-      gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[1]));
       if (reg_overlap_mentioned_p (operands[0], operands[3])
          || reg_overlap_mentioned_p (operands[0], operands[4]))
        {
 ;; ----------------------------------------------------------------------
 
 (define_insn "subsi3"
-  [(set (match_operand:SI           0 "register_operand"  "=r,r,r")
-       (minus:SI (match_operand:SI 1 "register_operand"   "0,0,r")
-                 (match_operand:SI 2 "nonmemory_operand"  "r,i,r")))
+  [(set (match_operand:SI           0 "register_operand"  "=r,r,r,r")
+       (minus:SI (match_operand:SI 1 "register_operand"   "0,0,0,r")
+                 (match_operand:SI 2 "nonmemory_operand"  "r,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
+   sub %2,%0
    sub %2,%0
    sub %2,%0
    sub %2,%1,%0"
-  [(set_attr "isa" "*,*,am33")
-   (set_attr "liw" "either,*,*")
+  [(set_attr "isa" "*,*,*,am33")
+   (set_attr "liw" "either,either,*,*")
    (set_attr "liw_op" "sub")
-   (set_attr "timings" "11,11,22")]
+   (set_attr "timings" "11,11,11,22")]
 )
 
 (define_insn "*subsi3_flags"
-  [(set (match_operand:SI           0 "register_operand"  "=r, r")
-       (minus:SI (match_operand:SI 1 "register_operand"   "0, r")
-                 (match_operand:SI 2 "nonmemory_operand"  "ri,r")))
-   (set (reg CC_REG)
-       (compare (minus:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (minus:SI (match_operand:SI 1 "register_operand"  "0, r")
+                          (match_operand:SI 2 "nonmemory_operand" "ri,r"))
+                (const_int 0)))
+   (set (match_operand:SI           0 "register_operand"  "=r, r")
+       (minus:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
   "@
    sub %2,%0
 
 ;; A helper to expand the above, with the CC_MODE filled in.
 (define_expand "subsi3_flags"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (minus:SI (match_operand:SI 1 "register_operand")
-                            (match_operand:SI 2 "nonmemory_operand")))
-             (set (reg:CCZNC CC_REG)
+  [(parallel [(set (reg:CCZNC CC_REG)
                   (compare:CCZNC (minus:SI (match_dup 1) (match_dup 2))
-                                 (const_int 0)))])]
+                                 (const_int 0)))
+             (set (match_operand:SI 0 "register_operand")
+                  (minus:SI (match_operand:SI 1 "register_operand")
+                            (match_operand:SI 2 "nonmemory_operand")))])]
   ""
 )
 
 ;; ??? Note that AM33 has a third multiply variant that puts the high part
 ;; into the MDRQ register, however this variant also constrains the inputs
 ;; to be in DATA_REGS and thus isn't as helpful as it might be considering
-;; the existance of the 4-operand multiply.  Nor is there a set of divide
+;; the existence of the 4-operand multiply.  Nor is there a set of divide
 ;; insns that use MDRQ.  Given that there is an IMM->MDRQ insn, this would
 ;; have been very handy for starting udivmodsi4...
 
 )
 
 (define_insn "*andsi3_flags"
-  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
-       (and:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
-               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
-   (set (reg CC_REG)
-       (compare (and:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (and:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+                        (match_operand:SI 2 "nonmemory_operand" " i,D,r"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (and:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "@
    and %2,%0
 )
 
 (define_insn "*iorsi3_flags"
-  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
-       (ior:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
-               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
-   (set (reg CC_REG)
-       (compare (ior:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (ior:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+                        (match_operand:SI 2 "nonmemory_operand" " i,D,r"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (ior:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "@
    or %2,%0
 )
 
 (define_insn "*xorsi3_flags"
-  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
-       (xor:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
-               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
-   (set (reg CC_REG)
-       (compare (xor:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (xor:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+                        (match_operand:SI 2 "nonmemory_operand" " i,D,r"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (xor:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "@
    xor %2,%0
 )
 
 (define_insn "*one_cmplsi2_flags"
-  [(set (match_operand:SI         0 "register_operand" "=D")
-       (not:SI (match_operand:SI 1 "register_operand" " 0")))
-   (set (reg CC_REG)
-       (compare (not:SI (match_dup 1))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (not:SI (match_operand:SI 1 "register_operand" "0"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand" "=D")
+       (not:SI (match_dup 1)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "not %0"
 )
   DONE;
 })
 
-(define_insn "*cmpsi"
+(define_insn "cmpsi"
   [(set (reg CC_REG)
-       (compare (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,r")
+                (match_operand:SI 1 "nonmemory_operand" "r,O,i")))]
   "reload_completed"
 {
   /* The operands of CMP must be distinct registers.  In the case where
 }
   [(set_attr_alternative "timings"
      [(if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))
+      (if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))
       (if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))])
-   (set_attr "liw" "either,*")
+   (set_attr "liw" "either,either,*")
    (set_attr "liw_op" "cmp")]
 )
 
 ;; ----------------------------------------------------------------------
 
 (define_insn "ashlsi3"
-  [(set (match_operand:SI  0 "register_operand"   "=r,D,d,d,D,D,r")
+  [(set (match_operand:SI  0 "register_operand"   "=r,D,d,d,D,D,D,r")
        (ashift:SI
-         (match_operand:SI 1 "register_operand"  " 0,0,0,0,0,0,r")
-         (match_operand:QI 2 "nonmemory_operand" " J,K,M,L,D,i,r")))
+         (match_operand:SI 1 "register_operand"  " 0,0,0,0,0,0,0,r")
+         (match_operand:QI 2 "nonmemory_operand" " J,K,M,L,D,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
    asl2 %0\;asl2 %0
    asl %S2,%0
    asl %S2,%0
+   asl %S2,%0
    asl %2,%1,%0"
-  [(set_attr "isa" "*,*,*,*,*,*,am33")
-   (set_attr "liw" "*,*,*,*,op2,*,*")
+  [(set_attr "isa" "*,*,*,*,*,*,*,am33")
+   (set_attr "liw" "op2,op2,op2,op2,op2,op2,*,*")
    (set_attr "liw_op" "asl")
-   (set_attr "timings" "11,11,22,22,11,11,11")]
+   (set_attr "timings" "11,11,22,22,11,11,11,11")]
 )
 
 (define_insn "lshrsi3"
-  [(set (match_operand:SI  0 "register_operand"  "=D,D,r")
+  [(set (match_operand:SI  0 "register_operand"  "=D,D,D,r")
        (lshiftrt:SI
-         (match_operand:SI 1 "register_operand"  "0,0,r")
-         (match_operand:QI 2 "nonmemory_operand" "D,i,r")))
+         (match_operand:SI 1 "register_operand"  "0,0,0,r")
+         (match_operand:QI 2 "nonmemory_operand" "D,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
+   lsr %S2,%0
    lsr %S2,%0
    lsr %S2,%0
    lsr %2,%1,%0"
-  [(set_attr "isa" "*,*,am33")
-   (set_attr "liw" "op2,*,*")
+  [(set_attr "isa" "*,*,*,am33")
+   (set_attr "liw" "op2,op2,*,*")
    (set_attr "liw_op" "lsr")]
 )
 
 (define_insn "ashrsi3"
-  [(set (match_operand:SI  0 "register_operand"  "=D,D,r")
+  [(set (match_operand:SI  0 "register_operand"  "=D,D,D,r")
        (ashiftrt:SI
-         (match_operand:SI 1 "register_operand"  "0,0,r")
-         (match_operand:QI 2 "nonmemory_operand" "D,i,r")))
+         (match_operand:SI 1 "register_operand"  "0,0,0,r")
+         (match_operand:QI 2 "nonmemory_operand" "D,O,i,r")))
    (clobber (reg:CC CC_REG))]
   ""
   "@
+   asr %S2,%0
    asr %S2,%0
    asr %S2,%0
    asr %2,%1,%0"
-  [(set_attr "isa" "*,*,am33")
-   (set_attr "liw" "op2,*,*")
+  [(set_attr "isa" "*,*,*,am33")
+   (set_attr "liw" "op2,op2,*,*")
    (set_attr "liw_op" "asr")]
 )
 
 ;; ----------------------------------------------------------------------
-;; MISCELANEOUS
+;; MISCELLANEOUS
 ;; ----------------------------------------------------------------------
 
+;; Note the use of the (const_int 0) when generating the insn that matches
+;; the bsch pattern.  This ensures that the destination register is
+;; initialised with 0 which will make the BSCH instruction set searching
+;; at bit 31.
+;;
+;; The XOR in the instruction sequence below is there because the BSCH
+;; instruction returns the bit number of the highest set bit and we want
+;; the number of zero bits above that bit.  The AM33 does not have a
+;; reverse subtraction instruction, but we can use a simple xor instead
+;; since we know that the top 27 bits are clear.
 (define_expand "clzsi2"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (unspec:SI [(match_operand:SI 1 "register_operand" "")
+  [(parallel [(set (match_operand:SI 0 "register_operand")
+                  (unspec:SI [(match_operand:SI 1 "register_operand")
                               (const_int 0)] UNSPEC_BSCH))
+             (clobber (reg:CC CC_REG))])
+   (parallel [(set (match_dup 0)
+                  (xor:SI (match_dup 0)
+                          (const_int 31)))
              (clobber (reg:CC CC_REG))])]
   "TARGET_AM33"
 )
                   UNSPEC_BSCH))
    (clobber (reg:CC CC_REG))]
   "TARGET_AM33"
-  "bsch %1,%0"
+  "bsch %1, %0"
 )
 
 ;; ----------------------------------------------------------------------
 {
   /* The RETF insn is up to 3 cycles faster than RET.  */
   fputs ((mn10300_can_use_retf_insn () ? "\tretf " : "\tret "), asm_out_file);
-  mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
+  mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs (NULL));
   fprintf (asm_out_file, ",%d\n", (int) INTVAL (operands[0]));
   return "";
 })
 {
   fputs ("\tmovm ", asm_out_file);
   mn10300_print_reg_list (asm_out_file,
-                          mn10300_store_multiple_operation (operands[0],
-                                                           VOIDmode));
+                          mn10300_store_multiple_regs (operands[0]));
   fprintf (asm_out_file, ",(sp)\n");
   return "";
 }
 (define_insn "liw"
   [(set (match_operand:SI             0 "register_operand" "=r")
        (unspec:SI [(match_dup 0)
-                    (match_operand:SI 2 "register_operand" "r")
+                    (match_operand    2 "liw_operand"       "rO")
                     (match_operand:SI 4 "const_int_operand" "")]
                    UNSPEC_LIW))
    (set (match_operand:SI             1 "register_operand" "=r")
         (unspec:SI [(match_dup 1)
-                    (match_operand    3 "register_operand" "r")
+                    (match_operand    3 "liw_operand"       "rO")
                     (match_operand:SI 5 "const_int_operand" "")]
                    UNSPEC_LIW))]
   "TARGET_ALLOW_LIW"
 (define_insn "cmp_liw"
   [(set (reg:CC CC_REG)
        (compare:CC (match_operand:SI 2 "register_operand" "r")
-                   (match_operand:SI 3 "register_operand" "r")))
+                   (match_operand    3 "liw_operand"      "rO")))
    (set (match_operand:SI             0 "register_operand" "=r")
         (unspec:SI [(match_dup 0)
-                    (match_operand    1 "register_operand" "r")
+                    (match_operand    1 "liw_operand"       "rO")
                     (match_operand:SI 4 "const_int_operand" "")]
                    UNSPEC_LIW))]
   "TARGET_ALLOW_LIW"
-  "cmp_%W4 %2, %3, %0, %1"
+  "cmp_%W4 %3, %2, %1, %0"
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 13) (const_int 12)))]
 )
 (define_insn "liw_cmp"
   [(set (match_operand:SI             0 "register_operand" "=r")
         (unspec:SI [(match_dup 0)
-                    (match_operand:SI 1 "register_operand" "r")
+                    (match_operand    1 "liw_operand"      "rO")
                     (match_operand:SI 4 "const_int_operand" "")]
                    UNSPEC_LIW))
    (set (reg:CC CC_REG)
        (compare:CC (match_operand:SI 2 "register_operand" "r")
-                   (match_operand:SI 3 "register_operand" "r")))]
+                   (match_operand    3 "liw_operand"      "rO")))]
   "TARGET_ALLOW_LIW"
-  "%W4_cmp %0, %1, %2, %3"
+  "%W4_cmp %1, %0, %3, %2"
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 13) (const_int 12)))]
 )
+
+;; Note - in theory the doloop patterns could be used here to express
+;; the SETLB and Lcc instructions.  In practice this does not work because
+;; the acceptable forms of the doloop patterns do not include UNSPECs
+;; and without them gcc's basic block reordering code can duplicate the
+;; doloop_end pattern, leading to bogus multiple decrements of the loop
+;; counter. 
+
+(define_insn "setlb"
+  [(unspec [(const_int 0)] UNSPEC_SETLB)]
+  "TARGET_AM33 && TARGET_ALLOW_SETLB"
+  "setlb"
+)
+
+(define_insn "Lcc"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                     [(reg:CC CC_REG) (const_int 0)])
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (unspec [(const_int 1)] UNSPEC_SETLB)]
+  "TARGET_AM33 && TARGET_ALLOW_SETLB"
+  "L%b0 # loop back to: %1"
+)
+
+(define_insn "FLcc"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                     [(reg:CC_FLOAT CC_REG) (const_int 0)])
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (unspec [(const_int 2)] UNSPEC_SETLB)]
+  "TARGET_AM33_2 && TARGET_ALLOW_SETLB"
+  "FL%b0 # loop back to: %1"
+  [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") (const_int 44) (const_int 11)))]
+)