OSDN Git Service

(notice_cc_update): Set CC_FCOMI is this is a float compare.
[pf3gnuchains/gcc-fork.git] / gcc / config / m88k / m88k.md
index d31a5f8..bf5124b 100644 (file)
@@ -1,8 +1,7 @@
 ;;- Machine description for the Motorola 88000 for GNU C compiler
-;;  Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+;;;  Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
 ;;  Contributed by Michael Tiemann (tiemann@mcc.com)
-;;  Additional changes by Michael Meissner (meissner@osf.org)
-;;  Currently supported by Tom Wood (wood@dg-rtp.dg.com)
+;;  Currently maintained by (gcc@dg-rtp.dg.com)
 
 ;; This file is part of GNU CC.
 
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU CC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
 
-;; SCCS rev field.  This is a NOP, just to get the SCCS id into the
+;; RCS rev field.  This is a NOP, just to get the RCS id into the
 ;; program image.
-(define_expand "m88k_sccs_id"
+(define_expand "m88k_rcs_id"
   [(match_operand:SI 0 "" "")]
   ""
-  "{ static char sccs_id[] = \"@(#)m88k.md     2.0.3.3 18 Mar 1992 15:40:12\";
+  "{ static char rcs_id[] = \"$What: <@(#) m88k.md,v   1.1.1.2.2.2> $\";
      FAIL; }")
 \f
-;; Attribute specifications
+;; Attribute describing the processor.  This attribute must match exactly
+;; with the processor_type enumeration in m88k.h.
 
 ; Target CPU.
-(define_attr "cpu" "m88000,m88100,m88110"
+(define_attr "cpu" "m88100,m88110,m88000"
   (const (symbol_ref "m88k_cpu")))
 
 ; Type of each instruction.  Default is arithmetic.
 ; I'd like to write the list as this, but genattrtab won't accept it.
 ;
 ; "branch,jump,call,                   ; flow-control instructions
-;  load,store,loada,                   ; data unit instructions
-;  spadd,dpadd,spdiv,dpdiv,idiv,       ; FPU add instructions
+;  load,store,loadd,loada,             ; data unit instructions
+;  spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv, ; FPU add instructions
 ;  spmul,dpmul,imul,                   ; FPU multiply instructions
-;  arith,                              ; integer unit instructions
-;  marith,mstore,mfp,weird"            ; multi-word instructions
+;  arith,bit,mov                       ; integer unit instructions
+;  marith,weird"                       ; multi-word instructions
 
 ; Classification of each insn.  Some insns of TYPE_BRANCH are multi-word.
 (define_attr "type"
-  "branch,jump,call,load,store,loada,spadd,dpadd,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,marith,mstore,mfp,weird"
+  "branch,jump,call,load,store,loadd,loada,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,bit,mov,marith,weird"
   (const_string "arith"))
 
-; Convenience attributes.
 (define_attr "fpu" "yes,no"
   (if_then_else
-   (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spdiv,dpdiv,idiv,mfp")
+   (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv")
    (const_string "yes") (const_string "no")))
 
 ; Length in # of instructions of each insn.  The values are not exact, but
 ; are safe.
 (define_attr "length" ""
-  (cond [(eq_attr "type" "marith,mstore,mfp")
+  (cond [(eq_attr "type" "marith,weird,branch")
         (const_int 2)]
        (const_int 1)))
 
@@ -80,8 +80,8 @@
 (define_delay (eq_attr "type" "branch,jump")
   [(and
     (and
-     (eq_attr "type" "!branch,jump,call,marith,mstore,mfp,weird") ; required.
-     (eq_attr "type" "!load")) ; issue as-soon-as-possible.
+     (eq_attr "type" "!branch,jump,call,marith,weird") ; required.
+     (eq_attr "type" "!load,loadd")) ; issue as-soon-as-possible.
     (eq_attr "fpu" "no")) ; issue as-soon-as-possible.
    (eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1)
 
@@ -89,7 +89,7 @@
 ; a call.  (@@ Support for this case is expected in reorg.c soon.)
 
 (define_delay (eq_attr "type" "call")
-  [(eq_attr "type" "!branch,call,marith,mstore,mfp,weird") ; required.
+  [(eq_attr "type" "!branch,call,marith,weird") ; required.
    (nil) (nil)])
 \f
 ; An abstract block diagram of the function units for the m88100.
 ; Consideration of writeback contention is critical to superb scheduling.
 ;
 ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
-;                      TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST])
+;                      TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
 
-;(define_function_unit "decode" 1 1 (const_int 1) 0 1)
-
-; Describing the alu is currently not useful.
+; Describing the '100 alu is currently not useful.
 ;(define_function_unit "alu" 1 0 (eq_attr "type"
-;                                       "!store,mstore,marith,mfp,weird") 1 0)
+;                                       "!store,marith,weird") 1 0)
 ;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0)
 
-(define_function_unit "memory" 1 3 (eq_attr "type" "load") 3 2)
+(define_function_unit "alu" 1 0
+  (and (eq_attr "type" "loada,arith,mov") (eq_attr "cpu" "!m88100")) 2 0)
+(define_function_unit "alu" 1 0
+  (and (eq_attr "type" "marith,weird") (eq_attr "cpu" "!m88100")) 4 0)
+
+(define_function_unit "bit" 1 0
+  (and (eq_attr "type" "bit") (eq_attr "cpu" "!m88100")) 2 2)
 
-; The fp1 and fplast descriptions currently have no effect.
-;(define_function_unit "fp1" 1 1 (eq_attr "fpu" "yes") 1 2)
+(define_function_unit "mem100" 1 0
+  (and (eq_attr "type" "store,loada") (eq_attr "cpu" "m88100")) 1 0)
+(define_function_unit "mem100" 1 0
+  (and (eq_attr "type" "load") (eq_attr "cpu" "m88100")) 3 0)
+(define_function_unit "mem100" 1 0
+  (and (eq_attr "type" "loadd") (eq_attr "cpu" "m88100")) 3 2)
+
+(define_function_unit "mem110" 1 0
+  (and (eq_attr "type" "load,loadd") (eq_attr "cpu" "!m88100")) 3 2)
+(define_function_unit "mem110" 1 0
+  (and (eq_attr "type" "store") (eq_attr "cpu" "!m88100")) 1 2)
 
 ; The times are adjusted to include fp1 and fplast, but then are further
 ; adjusted based on the actual generated code.  The notation to the right
 ; is the total latency.  A range denotes a group of instructions and/or
 ; conditions (the extra clock of fplast time with some sequences).
-(define_function_unit "fpmul" 1 4 (eq_attr "type" "spmul") 4 2)                ; 6-8
-(define_function_unit "fpmul" 1 4 (eq_attr "type" "dpmul,mfp") 7 2)    ; 9-10
-(define_function_unit "fpmul" 1 4 (eq_attr "type" "imul") 3 2)         ; 4
-
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "spadd") 3 2)                ; 5-6
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "dpadd") 4 2)                ; 6-7
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "spdiv") 30 2)       ; 30-31
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "dpdiv") 60 2)       ; 60-61
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "idiv") 38 2)                ; 38
-
-;(define_function_unit "fplast" 1 1 (eq_attr "fpu" "yes") 1 2)
-
-; Describing writeback contention is currently not useful.
-;(define_function_unit "writeback" 1 1
-;  (eq_attr "type" "!store,mstore,branch,jump,call") 0 1)
-
-; Describing stores is currently not useful.  The suggestion here is that the
-; function unit ordering has already been established (writeback is last) and
-; that store insns use the units in an unusual order.
-;(define_function_unit "writeback" 1 1 (eq_attr "type" "store,mstore") 0 1)
-;(define_function_unit "memory" 1 3 (eq_attr "type" "store,mstore") 1 2)
+
+(define_function_unit "fpmul100" 1 0
+  (and (eq_attr "type" "spmul") (eq_attr "cpu" "m88100")) 4 0)         ; 6-8
+(define_function_unit "fpmul100" 1 0
+  (and (eq_attr "type" "dpmul") (eq_attr "cpu" "m88100")) 7 0)         ; 9-10
+(define_function_unit "fpmul100" 1 0
+  (and (eq_attr "type" "imul") (eq_attr "cpu" "m88100")) 3 0)          ; 4
+
+(define_function_unit "fpmul110" 1 0
+  (and (eq_attr "type" "imul,spmul,dpmul")
+       (eq_attr "cpu" "!m88100")) 5 2)                                 ; 3
+
+(define_function_unit "fpadd100" 1 5
+  (and (eq_attr "type" "spadd,spcmp") (eq_attr "cpu" "m88100")) 3 0)   ; 5-6
+(define_function_unit "fpadd100" 1 5
+  (and (eq_attr "type" "dpadd,dpcmp") (eq_attr "cpu" "m88100")) 4 0)   ; 6-7
+
+(define_function_unit "fpadd110" 1 0
+  (and (eq_attr "type" "spadd,dpadd") (eq_attr "cpu" "!m88100")) 5 2)  ; 3
+(define_function_unit "fpadd110" 1 0
+  (and (eq_attr "type" "spcmp,dpcmp") (eq_attr "cpu" "!m88100")) 2 2)  ; 1
+
+(define_function_unit "fpadd100" 1 5
+  (and (eq_attr "type" "spdiv") (eq_attr "cpu" "m88100")) 30 0)                ; 30-31
+(define_function_unit "fpadd100" 1 5
+  (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "m88100")) 60 0)                ; 60-61
+(define_function_unit "fpadd100" 1 5
+  (and (eq_attr "type" "idiv") (eq_attr "cpu" "m88100")) 38 0)         ; 38
+
+(define_function_unit "div" 1 1
+  (and (eq_attr "type" "spdiv") (eq_attr "cpu" "!m88100")) 25 2)       ; 13
+(define_function_unit "div" 1 1
+  (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "!m88100")) 45 2)       ; 23
+(define_function_unit "div" 1 1
+  (and (eq_attr "type" "idiv") (eq_attr "cpu" "!m88100")) 35 2)                ; 18
 \f
-;; This rich set of complex patterns are mostly due to Torbjorn Granlund
-;; (tege@sics.se).  They've changed since then, so don't complain to him
-;; if they don't work right.
+;; Superoptimizer sequences
 
-;; Regarding shifts, gen_lshlsi3 generates ASHIFT.  LSHIFT opcodes are
-;; not produced and should not normally occur.  Also, the gen functions
-;; produce the necessary insns to support TARGET_*_LARGE_SHIFT, so nothing
-;; special needs to be done here.
+;; geu+: { r = ((unsigned_word) v0 >= (unsigned_word) v1) + v2; }
+;;      subu.co r5,r2,r3
+;;      addu.cio r6,r4,r0
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (minus:SI (match_operand:SI 1 "register_operand" "r")
+                 (geu:SI (match_operand:SI 2 "register_operand" "r")
+                         (match_operand:SI 3 "register_operand" "r"))))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+   (set (match_dup 0)
+       (plus:SI (match_dup 1)
+                (unspec:SI [(const_int 0)
+                            (reg:CC 0)] 0)))]
+  "")
 
-;; (a << int1) >> int2 optimizations into a single extract.
-;; These patterns need to occur before the normal shift patterns
+;; leu+: { r = ((unsigned_word) v0 <= (unsigned_word) v1) + v2; }
+;;      subu.co r5,r3,r2
+;;      addu.cio r6,r4,r0
 
-(define_insn ""
+(define_split
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
-                               (match_operand:SI 2 "int5_operand" ""))
-                    (match_operand:SI 3 "int5_operand" "")))]
-  "INTVAL (operands [2]) <= INTVAL (operands [3])"
-  "*
-{
-  operands[4] = gen_rtx (CONST_INT, SImode,
-                        INTVAL (operands[3]) - INTVAL (operands[2]));
-  return \"ext %0,%1,%w3<%4>\";  /* <(%3-%2)> */
-}")
+       (minus:SI (match_operand:SI 1 "register_operand" "r")
+                 (leu:SI (match_operand:SI 3 "register_operand" "r")
+                         (match_operand:SI 2 "register_operand" "r"))))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+   (set (match_dup 0)
+       (plus:SI (match_dup 1)
+                (unspec:SI [(const_int 0)
+                            (reg:CC 0)] 0)))]
+  "")
 
-(define_insn ""
+;; eq0+: { r = (v0 == 0) + v1; }
+;;      subu.co r4,r0,r2
+;;      addu.cio r5,r3,r0
+
+(define_split
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (lshiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
-                               (match_operand:SI 2 "int5_operand" ""))
-                    (match_operand:SI 3 "int5_operand" "")))]
-  "INTVAL (operands [2]) <= INTVAL (operands [3])"
-  "*
-{
-  operands[4] = gen_rtx (CONST_INT, SImode,
-                        INTVAL (operands[3]) - INTVAL (operands[2]));
-  return \"extu %0,%1,%w3<%4>\";  /* <(%3-%2)> */
-}")
+       (minus:SI (match_operand:SI 1 "register_operand" "r")
+                 (eq:SI (match_operand:SI 2 "register_operand" "r")
+                        (const_int 0))))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1))
+   (set (match_dup 0)
+       (plus:SI (match_dup 1)
+                (unspec:SI [(const_int 0)
+                            (reg:CC 0)] 0)))]
+  "")
+
+;; ltu-:  { r = v2 - ((unsigned_word) v0 < (unsigned_word) v1); }
+;;      subu.co r5,r2,r3
+;;      subu.cio r6,r4,r0
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (ltu:SI (match_operand:SI 2 "register_operand" "r")
+                        (match_operand:SI 3 "register_operand" "r"))
+                (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+   (set (match_dup 0)
+       (minus:SI (match_dup 1)
+                 (unspec:SI [(const_int 0)
+                             (reg:CC 0)] 1)))]
+  "")
+
+;; gtu-: { r = v2 - ((unsigned_word) v0 > (unsigned_word) v1); }
+;;      subu.co r5,r3,r2
+;;      subu.cio r6,r4,r0
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (gtu:SI (match_operand:SI 3 "register_operand" "r")
+                        (match_operand:SI 2 "register_operand" "r"))
+                (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+   (set (match_dup 0)
+       (minus:SI (match_dup 1)
+                (unspec:SI [(const_int 0)
+                            (reg:CC 0)] 1)))]
+  "")
+
+;; ne0-: { r = v1 - (v0 != 0); }
+;;      subu.co r4,r0,r2
+;;      subu.cio r5,r3,r0
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (ne:SI (match_operand:SI 2 "register_operand" "r")
+                       (const_int 0))
+                (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1))
+   (set (match_dup 0)
+       (minus:SI (match_dup 1)
+                 (unspec:SI [(const_int 0)
+                             (reg:CC 0)] 1)))]
+  "")
+
+;; ges0-: { r = v1 - ((signed_word) v0 >= 0); }
+;;     addu.co r4,r2,r2
+;;     subu.cio r5,r3,r0
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (minus:SI (match_operand:SI 1 "register_operand" "r")
+                 (xor:SI (lshiftrt:SI
+                          (match_operand:SI 2 "register_operand" "r")
+                          (const_int 31))
+                         (const_int 1))))]
+  ""
+  [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 2)] 0))
+   (set (match_dup 0)
+       (minus:SI (match_dup 1)
+                 (unspec:SI [(const_int 0)
+                             (reg:CC 0)] 1)))]
+  "")
+\f
+;; This rich set of complex patterns are mostly due to Torbjorn Granlund
+;; (tege@sics.se).  They've changed since then, so don't complain to him
+;; if they don't work right.
+
+;; Regarding shifts, gen_lshlsi3 generates ASHIFT.  The gen functions
+;; produce the necessary insns to support TARGET_*_LARGE_SHIFT, so nothing
+;; special needs to be done here.
 
 ;; Optimize possible cases of the set instruction.
 
         (ashift:SI (const_int -1)
                    (match_operand:SI 1 "register_operand" "r")))]
   ""
-  "set %0,%#r0,%1")
+  "set %0,%#r0,%1"
+  [(set_attr "type" "bit")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
                            (match_operand:SI 1 "register_operand" "r"))
                 (match_operand:SI 2 "register_operand" "r")))]
   ""
-  "set %0,%2,%1")
+  "set %0,%2,%1"
+  [(set_attr "type" "bit")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
                 (ashift:SI (const_int -1)
                            (match_operand:SI 2 "register_operand" "r"))))]
   ""
-  "set %0,%1,%2")
+  "set %0,%1,%2"
+  [(set_attr "type" "bit")])
 
 ;; Optimize possible cases of the mak instruction.
 
                         exact_log2 (1 + (INTVAL (operands[3])
                                          >> INTVAL(operands[2]))));
   return \"mak %0,%1,%4<%2>\";
-}")
+}"
+  [(set_attr "type" "bit")])
 
 ;; Optimize possible cases of output_and.
 
               ((1 << INTVAL (operands[2])) - 1) << INTVAL (operands[4]));
   return output_and (operands);
 }"
-  [(set_attr "type" "marith")]) ; length is 1 or 2.
+  [(set_attr "type" "marith")]) ; arith,bit,marith.  length is 1 or 2.
+\f
+;; Improve logical operations on compare words
+;;
+;; We define all logical operations on CCmode values to preserve the pairwise
+;; relationship of the compare bits.  This allows a future branch prediction
+;; pass the degree of freedom needed to change and/bb0-le into or/bb1-gt.
+;; THIS IS CURRENTLY FALSE! 
+;;
+;; Opportunities arise when conditional expressions using && and || are made
+;; unconditional.  When these are used to branch, the sequence is
+;; cmp/cmp/extu/extu/{and,or}/bcnd-{eq0,ne0}.  When these are used to create
+;; a value, the sequence is cmp/cmp/extu/extu/{and,or} for 1 or 0 or
+;; cmp/cmp/ext/ext/{and,or} for -1 or 0.
+;;
+;; When the extracted conditions are the same, the define_split patterns
+;; below change extu/extu/{and,or} into {and,or}/extu.  If the reversed
+;; conditions match, one compare word can be complimented, resulting in
+;; {and.c,or.c}/extu.  These changes are done for ext/ext/{and,or} as well.
+;; If the conditions don't line up, one can be rotated.  To keep the pairwise
+;; relationship, it may be necessary to both rotate and compliment.  Rotating
+;; makes branching cheaper, but doesn't help (or hurt) creating a value, so
+;; we don't do this for ext/ext/{and,or}.
+;;
+;; These changes result in the sequence extu/bcnd-{eq0,ne0} which is combined
+;; into an alternate form of bb0 and bb1.
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (neg:SI 
+                (match_operator 1 "even_relop"
+                                [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "relop"
+                                [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (ior:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   if (GET_CODE (operands[1]) == GET_CODE (operands[3]))
+     ; /* The conditions match.  */
+   else if (GET_CODE (operands[1])
+           == reverse_condition (GET_CODE (operands[3])))
+     /* Reverse the condition by complimenting the compare word.  */
+     operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+   else
+     {
+       /* Make the condition pairs line up by rotating the compare word.  */
+       int cv1 = condition_value (operands[1]);
+       int cv2 = condition_value (operands[3]);
+
+       operands[4] = gen_rtx (ROTATE, CCmode, operands[4],
+                             gen_rtx (CONST_INT, VOIDmode,
+                                      ((cv2 & ~1) - (cv1 & ~1)) & 0x1f));
+       /* Reverse the condition if needed.  */
+       if ((cv1 & 1) != (cv2 & 1))
+        operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+     }")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (neg:SI 
+                (match_operator 1 "odd_relop"
+                                [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "odd_relop"
+                                [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (and:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   if (GET_CODE (operands[1]) == GET_CODE (operands[3]))
+     ; /* The conditions match.  */
+   else
+     {
+       /* Make the condition pairs line up by rotating the compare word.  */
+       int cv1 = condition_value (operands[1]);
+       int cv2 = condition_value (operands[3]);
+
+       operands[4] = gen_rtx (ROTATE, CCmode, operands[4],
+                             gen_rtx (CONST_INT, VOIDmode,
+                                      (cv2 - cv1) & 0x1f));
+     }")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (neg:SI 
+                (match_operator 1 "odd_relop"
+                                [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "even_relop"
+                                [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (ior:CCEVEN (not:CC (match_dup 2))
+               (match_dup 4)))
+   (set (match_dup 0)
+       (neg:SI (match_op_dup 3 [(match_dup 5) (const_int 0)])))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+  if (GET_CODE (operands[1])
+           == reverse_condition (GET_CODE (operands[3])))
+     ; 
+   else
+     {
+       /* Make the condition pairs line up by rotating the compare word.  */
+       int cv1 = condition_value (operands[1]);
+       int cv2 = condition_value (operands[3]);
+
+       operands[2] = gen_rtx (ROTATE, CCmode, operands[2],
+                             gen_rtx (CONST_INT, VOIDmode,
+                                      ((cv1 & ~1) - (cv2 & ~1)) & 0x1f));
+     }")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (match_operator 1 "even_relop"
+                               [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "relop"
+                               [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                (const_int 0)])))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  "GET_CODE (operands[1]) == GET_CODE (operands[3])
+   || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))"
+  [(set (match_dup 5)
+       (ior:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   /* Reverse the condition by  complimenting the compare word.  */
+   if (GET_CODE (operands[1]) != GET_CODE (operands[3]))
+      operands[4] = gen_rtx (NOT, CCmode, operands[4]);")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (match_operator 1 "odd_relop"
+                               [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "odd_relop"
+                               [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                (const_int 0)])))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  "GET_CODE (operands[1]) == GET_CODE (operands[3])"
+  [(set (match_dup 5)
+       (and:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (match_operator 1 "odd_relop"
+                               [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "even_relop"
+                               [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                (const_int 0)])))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  "GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))"
+  [(set (match_dup 5)
+       (ior:CCEVEN (not:CC (match_dup 4))
+               (match_dup 2)))
+   (set (match_dup 0)
+       (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (neg:SI 
+                (match_operator 1 "even_relop"
+                                [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "relop"
+                                [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (and:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   if (GET_CODE (operands[1]) == GET_CODE (operands[3]))
+     ; /* The conditions match.  */
+   else if (GET_CODE (operands[1])
+           == reverse_condition (GET_CODE (operands[3])))
+     /* Reverse the condition by complimenting the compare word.  */
+     operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+   else
+     {
+       /* Make the condition pairs line up by rotating the compare word.  */
+       int cv1 = condition_value (operands[1]);
+       int cv2 = condition_value (operands[3]);
+       operands[4] = gen_rtx (ROTATE, CCmode, operands[4],
+                             gen_rtx (CONST_INT, VOIDmode,
+                                      ((cv2 & ~1) - (cv1 & ~1)) & 0x1f));
+       /* Reverse the condition if needed.  */
+       if ((cv1 & 1) != (cv2 & 1))
+        operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+     }")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (neg:SI 
+                (match_operator 1 "odd_relop"
+                                [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "odd_relop"
+                                [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (ior:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   if (GET_CODE (operands[1]) == GET_CODE (operands[3]))
+     ; /* The conditions match.  */
+   else
+     {
+       /* Make the condition pairs line up by rotating the compare word.  */
+       int cv1 = condition_value (operands[1]);
+       int cv2 = condition_value (operands[3]);
+       operands[4] = gen_rtx (ROTATE, CCmode, operands[4],
+                             gen_rtx (CONST_INT, VOIDmode,
+                                      (cv2 - cv1) & 0x1f));
+     }")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (neg:SI 
+                (match_operator 1 "odd_relop"
+                                [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "even_relop"
+                                [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (and:CCEVEN (not:CC (match_dup 2))
+               (match_dup 4)))
+   (set (match_dup 0)
+       (neg:SI (match_op_dup 3 [(match_dup 5) (const_int 0)])))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   if (GET_CODE (operands[1])
+           == reverse_condition (GET_CODE (operands[3])))
+       ;
+   else
+     {
+       /* Make the condition pairs line up by rotating the compare word.  */
+       int cv1 = condition_value (operands[1]);
+       int cv2 = condition_value (operands[3]);
+       operands[2] = gen_rtx (ROTATE, CCmode, operands[2],
+                             gen_rtx (CONST_INT, VOIDmode,
+                                      ((cv1 & ~1) - (cv2 & ~1)) & 0x1f));
+     }")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (match_operator 1 "even_relop"
+                               [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "relop"
+                               [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                (const_int 0)])))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  "GET_CODE (operands[1]) == GET_CODE (operands[3])
+   || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))"
+  [(set (match_dup 5)
+       (and:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);
+   /* Reverse the condition by  complimenting the compare word.  */
+   if (GET_CODE (operands[1]) != GET_CODE (operands[3]))
+      operands[4] = gen_rtx (NOT, CCmode, operands[4]);")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (match_operator 1 "odd_relop"
+                               [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "odd_relop"
+                               [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                (const_int 0)])))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  "GET_CODE (operands[1]) == GET_CODE (operands[3])"
+  [(set (match_dup 5)
+       (ior:CCEVEN (match_dup 4)
+               (match_dup 2)))
+   (set (match_dup 0)
+       (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (and:SI (match_operator 1 "odd_relop"
+                               [(match_operand 2 "partial_ccmode_register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "even_relop"
+                               [(match_operand 4 "partial_ccmode_register_operand" "r")
+                                (const_int 0)])))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  "GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))"
+  [(set (match_dup 5)
+       (and:CCEVEN (not:CC (match_dup 2))
+               (match_dup 4)))
+   (set (match_dup 0)
+       (match_op_dup 3 [(match_dup 5) (const_int 0)]))]
+  "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);")
+
+\f
+;; Logical operations on compare words.
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (and:CCEVEN (not:CC (match_operand 1 "partial_ccmode_register_operand" "r"))
+               (match_operand 2 "partial_ccmode_register_operand" "r")))]
+  ""
+  "and.c %0,%2,%1")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (and:CCEVEN (match_operand 1 "partial_ccmode_register_operand" "%r")
+               (match_operand 2 "partial_ccmode_register_operand" "r")))]
+  ""
+  "and %0,%1,%2")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (ior:CCEVEN (not:CC (match_operand 1 "partial_ccmode_register_operand" "r"))
+               (match_operand 2 "partial_ccmode_register_operand" "r")))]
+  ""
+  "or.c %0,%2,%1")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (ior:CCEVEN (match_operand 1 "partial_ccmode_register_operand" "%r")
+               (match_operand 2 "partial_ccmode_register_operand" "r")))]
+  ""
+  "or %0,%1,%2")
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                  (match_operand:CC 2 "int5_operand" "")))]
+  ""
+  "rot %0,%1,%2"
+  [(set_attr "type" "bit")])
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                  (match_operand:CC 2 "int5_operand" "")))]
+  ""
+  "rot %0,%1,%2"
+  [(set_attr "type" "bit")])
+
+;; rotate/and[.c] and rotate/ior[.c]
+
+(define_split
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (ior:CCEVEN (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (ior:CCEVEN (match_dup 4) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (ior:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_scratch:CCEVEN 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (ior:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (ior:CCEVEN (not:CC (match_dup 4)) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (ior:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_scratch:CCEVEN 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (and:CCEVEN (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (and:CCEVEN (match_dup 4) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (and:CCEVEN (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_scratch:CCEVEN 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (and:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (and:CCEVEN (not:CC (match_dup 4)) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CCEVEN 0 "register_operand" "=r")
+       (and:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand 3 "partial_ccmode_register_operand" "r")))
+   (clobber (match_scratch:CCEVEN 4 "=r"))]
+  ""
+  "#")
+
 \f
 ;; Recognize bcnd instructions for integer values.  This is distinguished
 ;; from a conditional branch instruction (below) with SImode instead of
       operands[3] = op2;
     }
   if (GET_CODE (operands[3]) == LABEL_REF)
-    return \"bcnd%. 0x5,%1,%3\;bcnd %#ne0,%d1,%3\";
+    return \"bcnd 0x5,%1,%3\;bcnd %#ne0,%d1,%3\";
 
   operands[3] = gen_label_rtx ();
   label_num = XINT (operands[3], 3);
-  output_asm_insn (\"bcnd%. 0x5,%1,%3\;bcnd %#eq0,%d1,%2\", operands);
+  output_asm_insn (\"bcnd 0x5,%1,%3\;bcnd %#eq0,%d1,%2\", operands);
   output_label (label_num);
   return \"\";
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "weird")
+   (set_attr "length" "3")])
 \f
 ;; Recognize bb0 and bb1 instructions.  These use two unusual template
 ;; patterns, %Lx and %Px.  %Lx outputs a 1 if operand `x' is a LABEL_REF
   "cmp %0,%r1,%2")
 
 (define_insn ""
-  [(set (match_operand:CC 0 "register_operand" "=r,r")
-       (compare:CC (match_operand:SF 1 "register_operand" "r,r")
-                   (match_operand:SF 2 "real_or_0_operand" "r,G")))]
+  [(set (match_operand:CC 0 "register_operand" "=r,r,r,r")
+       (compare:CC (match_operand:SF 1 "register_operand" "r,r,x,x")
+                   (match_operand:SF 2 "real_or_0_operand" "r,G,x,G")))]
   ""
   "@
    fcmp.sss %0,%1,%2
-   fcmp.sss %0,%1,%#r0"
-  [(set_attr "type" "spadd")])
+   fcmp.sss %0,%1,%#r0
+   fcmp.sss %0,%1,%2
+   fcmp.sss %0,%1,%#x0"
+  [(set_attr "type" "spcmp")])
 
 (define_insn ""
-  [(set (match_operand:CC 0 "register_operand" "=r")
-       (compare:CC (match_operand:DF 1 "register_operand" "r")
+  [(set (match_operand:CC 0 "register_operand" "=r,r")
+       (compare:CC (match_operand:DF 1 "register_operand" "r,x")
                    (float_extend:DF
-                    (match_operand:SF 2 "register_operand" "r"))))]
+                    (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fcmp.sds %0,%1,%2"
-  [(set_attr "type" "dpadd")])
+  [(set_attr "type" "dpcmp")])
 
 (define_insn ""
-  [(set (match_operand:CC 0 "register_operand" "=r")
+  [(set (match_operand:CC 0 "register_operand" "=r,r")
        (compare:CC (float_extend:DF
-                    (match_operand:SF 1 "register_operand" "r"))
-                   (match_operand:DF 2 "register_operand" "r")))]
+                    (match_operand:SF 1 "register_operand" "r,x"))
+                   (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fcmp.ssd %0,%1,%2"
-  [(set_attr "type" "dpadd")])
+  [(set_attr "type" "dpcmp")])
 
 (define_insn ""
-  [(set (match_operand:CC 0 "register_operand" "=r,r")
-       (compare:CC (match_operand:DF 1 "register_operand" "r,r")
-                   (match_operand:DF 2 "real_or_0_operand" "r,G")))]
+  [(set (match_operand:CC 0 "register_operand" "=r,r,r,r")
+       (compare:CC (match_operand:DF 1 "register_operand" "r,r,x,x")
+                   (match_operand:DF 2 "real_or_0_operand" "r,G,x,G")))]
   ""
   "@
    fcmp.sdd %0,%1,%2
-   fcmp.sds %0,%1,%#r0"
-  [(set_attr "type" "dpadd")])
+   fcmp.sds %0,%1,%#r0
+   fcmp.sdd %0,%1,%2
+   fcmp.sds %0,%1,%#x0"
+  [(set_attr "type" "dpcmp")])
 \f
 ;; Store condition code insns.  The compare insns set a register
 ;; rather than cc0 and record that register for use here.  See above
 ;; for the special treatment of cmpsi with a constant operand.
 
+;; @@ For the m88110, use fcmpu for bxx sxx inequality comparisons.
+
 (define_expand "seq"
   [(set (match_operand:SI 0 "register_operand" "")
        (match_dup 1))]
                           [(match_operand:CC 2 "register_operand" "r")
                            (const_int 0)]))]
   ""
-  "ext %0,%2,1<%C1>")
+  "ext %0,%2,1<%C1>"
+  [(set_attr "type" "bit")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (match_operator:SI 1 "even_relop"
+                          [(match_operand:CCEVEN 2 "register_operand" "r")
+                           (const_int 0)]))]
+  ""
+  "ext %0,%2,1<%C1>"
+  [(set_attr "type" "bit")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (not:SI (match_operator:SI 1 "odd_relop"
+                          [(match_operand:CCEVEN 2 "register_operand" "r")
+                           (const_int 0)])))]
+  ""
+  "ext %0,%2,1<%!%C1>"
+  [(set_attr "type" "bit")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (match_operator:SI 1 "odd_relop"
+                          [(match_operand:CCEVEN 2 "register_operand" "r")
+                           (const_int 0)]))
+   (clobber (match_operand:SI 3 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 3) (not:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])))
+   (set (match_dup 0) (not:SI (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (match_operator:SI 1 "odd_relop"
+                          [(match_operand:CCEVEN 2 "register_operand" "r")
+                           (const_int 0)]))
+   (clobber (match_scratch:SI 3 "=r"))]
+  ""
+  "#")
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
                            [(match_operand:CC 2 "register_operand" "r")
                             (const_int 0)])))]
   ""
-  "extu %0,%2,1<%C1>")
+  "extu %0,%2,1<%C1>"
+  [(set_attr "type" "bit")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI
+        (match_operator:SI 1 "even_relop"
+                           [(match_operand:CCEVEN 2 "register_operand" "r")
+                            (const_int 0)])))]
+  ""
+  "extu %0,%2,1<%C1>"
+  [(set_attr "type" "bit")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI
+        (not:SI (match_operator:SI 1 "odd_relop"
+                           [(match_operand:CCEVEN 2 "register_operand" "r")
+                            (const_int 0)]))))]
+  ""
+  "extu %0,%2,1<%!%C1>"
+  [(set_attr "type" "bit")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI (match_operator:SI 1 "odd_relop"
+                          [(match_operand:CCEVEN 2 "register_operand" "r")
+                           (const_int 0)])))
+   (clobber (match_operand:SI 3 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 3) (neg:SI (not:SI (match_op_dup 1 [(match_dup 2)
+                                                       (const_int 0)]))))
+   (set (match_dup 0) (xor:SI (match_dup 3) (const_int 1)))]
+  "")
+
+(define_insn
+ ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI (match_operator:SI 1 "odd_relop"
+                          [(match_operand:CCEVEN 2 "register_operand" "r")
+                           (const_int 0)])))
+   (clobber (match_scratch:SI 3 "=r"))]
+  ""
+  "#")
+
+
+
 \f
 ;; Conditional branch insns.  The compare insns set a register
 ;; rather than cc0 and record that register for use here.  See above
              (match_operand 2 "pc_or_label_ref" "")
              (match_operand 3 "pc_or_label_ref" "")))]
   ""
-  "bb1%. %R3%C0,%1,%P2%P3"
+  "*
+{
+  if (mostly_false_jump (insn, operands[0]))
+    return \"bb0%. %R2%C0,%1,%P2%P3\";
+  else
+    return \"bb1%. %R3%C0,%1,%P2%P3\";
+}"
+  [(set_attr "type" "branch")])
+
+;;
+;; Here branch prediction is sacrificed. To get it back, you need 
+;;  - CCODD (CC mode where the ODD bits are valid)
+;;  - several define_split that can apply De Morgan's Law.
+;;  - transformations between CCEVEN and CCODD modes. 
+;;  
+
+(define_insn ""
+  [(set (pc) (if_then_else
+             (match_operator 0 "even_relop"
+                             [(match_operand:CCEVEN 1 "register_operand" "r")
+                              (const_int 0)])
+             (match_operand 2 "pc_or_label_ref" "")
+             (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L2%. %C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+
+(define_insn ""
+  [(set (pc) (if_then_else
+             (match_operator 0 "odd_relop"
+                             [(match_operand:CCEVEN 1 "register_operand" "r")
+                              (const_int 0)])
+             (match_operand 2 "pc_or_label_ref" "")
+             (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L3%. %!%C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+
+;; Branch conditional on scc values.  These arise from manipulations on
+;; compare words above.
+;; Are these really used ? 
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
+        (ne (match_operator 0 "relop"
+                            [(match_operand:CC 1 "register_operand" "r")
+                             (const_int 0)])
+            (const_int 0))
+        (match_operand 2 "pc_or_label_ref" "")
+        (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L2 %C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
+        (ne (match_operator 0 "even_relop"
+                            [(match_operand:CCEVEN 1 "register_operand" "r")
+                             (const_int 0)])
+            (const_int 0))
+        (match_operand 2 "pc_or_label_ref" "")
+        (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L2 %C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
+        (ne (match_operator 0 "odd_relop"
+                            [(match_operand:CCEVEN 1 "register_operand" "r")
+                             (const_int 0)])
+            (const_int 0))
+        (match_operand 2 "pc_or_label_ref" "")
+        (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L3 %!%C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
+        (eq (match_operator 0 "relop"
+                            [(match_operand:CC 1 "register_operand" "r")
+                             (const_int 0)])
+            (const_int 0))
+        (match_operand 2 "pc_or_label_ref" "")
+        (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L3 %C0,%1,%P2%P3"
   [(set_attr "type" "branch")])
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
+        (eq (match_operator 0 "even_relop"
+                            [(match_operand:CCEVEN 1 "register_operand" "r")
+                             (const_int 0)])
+            (const_int 0))
+        (match_operand 2 "pc_or_label_ref" "")
+        (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L3 %C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
+        (eq (match_operator 0 "odd_relop"
+                            [(match_operand:CCEVEN 1 "register_operand" "r")
+                             (const_int 0)])
+            (const_int 0))
+        (match_operand 2 "pc_or_label_ref" "")
+        (match_operand 3 "pc_or_label_ref" "")))]
+  ""
+  "bb%L2 %!%C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
+\f
+(define_insn "locate1"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (high:SI (unspec:SI [(label_ref (match_operand 1 "" ""))] 0)))]
+  ""
+  "or.u %0,%#r0,%#hi16(%1#abdiff)")
+
+(define_insn "locate2"
+  [(parallel [(set (reg:SI 1) (pc))
+             (set (match_operand:SI 0 "register_operand" "=r")
+                  (lo_sum:SI (match_dup 0)
+                             (unspec:SI
+                              [(label_ref (match_operand 1 "" ""))] 0)))])]
+  ""
+  "bsr.n %1\;or %0,%0,%#lo16(%1#abdiff)\\n%1:"
+  [(set_attr "length" "2")])
 \f
 ;; SImode move instructions
 
   ""
   "
 {
-  if (emit_move_sequence (operands, SImode))
+  if (emit_move_sequence (operands, SImode, 0))
     DONE;
 }")
 
+(define_expand "reload_insi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (match_operand:SI 1 "general_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&r"))]
+  ""
+  "
+{
+  if (emit_move_sequence (operands, SImode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+  DONE;
+}")
+
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r")
-       (match_operand:SI 1 "move_operand" "rI,m,rO,J,M"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,x,x,x,m")
+       (match_operand:SI 1 "move_operand" "rI,m,rO,J,M,x,r,x,m,x"))]
   "(register_operand (operands[0], SImode)
     || register_operand (operands[1], SImode)
     || operands[1] == const0_rtx)"
   "@
    or %0,%#r0,%1
-   ld %0,%1
-   st %r1,%0
+   %V1ld\\t %0,%1
+   %v0st\\t %r1,%0
    subu %0,%#r0,%n1
-   set %0,%#r0,%s1"
-  [(set_attr "type" "arith,load,store,arith,arith")])
+   set %0,%#r0,%s1
+   mov.s %0,%1
+   mov.s %0,%1
+   mov %0,%1
+   %V1ld\\t %0,%1
+   %v0st\\t %1,%0"
+  [(set_attr "type" "arith,load,store,arith,bit,mov,mov,mov,load,store")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
    or.u %0,%#r0,%X1
    set %0,%#r0,%s1
    or.u %0,%#r0,%X1\;or %0,%0,%x1"
-  [(set_attr "type" "arith,arith,arith,arith,marith")])
+  [(set_attr "type" "arith,arith,arith,bit,marith")])
 
 ;; @@ Why the constraint "in"?  Doesn't `i' include `n'?
 (define_insn ""
   ""
   "or %0,%1,%#lo16(%g2)")
 
+;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
+;; confuse them with real addresses.
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+                  (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
+  ""
+  "or %0,%1,%#lo16(%g2)"
+  ;; Need to set length for this arith insn because operand2
+  ;; is not an "arith_operand".
+  [(set_attr "length" "1")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (high:SI (match_operand 1 "" "")))]
   ""
   "or.u %0,%#r0,%#hi16(%g1)")
 
+;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
+;; confuse them with real addresses.
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
+  ""
+  "or.u %0,%#r0,%#hi16(%g1)"
+  ;; Need to set length for this arith insn because operand2
+  ;; is not an arith_operand.
+  [(set_attr "length" "1")])
+
 ;; HImode move instructions
 
 (define_expand "movhi"
   ""
   "
 {
-  if (emit_move_sequence (operands, HImode))
+  if (emit_move_sequence (operands, HImode, 0))
     DONE;
 }")
 
     || operands[1] == const0_rtx)"
   "@
    or %0,%#r0,%h1
-   ld.hu %0,%1
-   st.h %r1,%0
+   %V1ld.hu\\t %0,%1
+   %v0st.h\\t %r1,%0
    subu %0,%#r0,%H1"
   [(set_attr "type" "arith,load,store,arith")])
 
   ""
   "
 {
-  if (emit_move_sequence (operands, QImode))
+  if (emit_move_sequence (operands, QImode, 0))
     DONE;
 }")
 
     || operands[1] == const0_rtx)"
   "@
    or %0,%#r0,%q1
-   ld.bu %0,%1
-   st.b %r1,%0
+   %V1ld.bu\\t %0,%1
+   %v0st.b\\t %r1,%0
    subu %r0,%#r0,%Q1"
   [(set_attr "type" "arith,load,store,arith")])
 
   ""
   "
 {
-  if (emit_move_sequence (operands, DImode))
+  if (emit_move_sequence (operands, DImode, 0))
     DONE;
 }")
 
 (define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
+  [(set (match_operand:DI 0 "register_operand" "=r,x")
        (const_int 0))]
   ""
-  "or %0,%#r0,0\;or %d0,%#r0,0"
-  [(set_attr "type" "marith")])
+  "@
+   or %0,%#r0,0\;or %d0,%#r0,0
+   mov %0,%#x0"
+  [(set_attr "type" "marith,mov")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
-       (match_operand:DI 1 "nonimmediate_operand" "r,m,r"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,x,x,x,m")
+       (match_operand:DI 1 "nonimmediate_operand" "r,m,r,x,r,x,m,x"))]
   ""
   "@
    or %0,%#r0,%1\;or %d0,%#r0,%d1
-   ld.d %0,%1
-   st.d %1,%0"
-  [(set_attr "type" "marith,load,store")])
+   %V1ld.d\\t %0,%1
+   %v0st.d\\t %1,%0
+   mov.d %0,%1
+   mov.d %0,%1
+   mov %0,%1
+   %V1ld.d\\t %0,%1
+   %v0st.d\\t %1,%0"
+  [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
   ""
   "
 {
-  if (emit_move_sequence (operands, DFmode))
+  if (emit_move_sequence (operands, DFmode, 0))
     DONE;
 }")
 
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "=r")
+       (match_operand:DF 1 "register_operand" "r"))]
+  "reload_completed
+   && GET_CODE (operands[0]) == REG && !XRF_REGNO_P (REGNO (operands[0]))
+   && GET_CODE (operands[1]) == REG && !XRF_REGNO_P (REGNO (operands[1]))"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 4) (match_dup 5))]
+  "
+{ operands[2] = operand_subword (operands[0], 0, 0, DFmode);
+  operands[3] = operand_subword (operands[1], 0, 0, DFmode);
+  operands[4] = operand_subword (operands[0], 1, 0, DFmode);
+  operands[5] = operand_subword (operands[1], 1, 0, DFmode); }")
+
 ;; @@ This pattern is incomplete and doesn't appear necessary.
 ;;
 ;; This pattern forces (set (reg:DF ...) (const_double ...))
 ;      return \"or %0,%#r0,0\;or %d0,%#r0,0\";
 ;    case 1:
 ;      operands[1] = adj_offsettable_operand (operands[0], 4);
-;      return \"st %#r0,%0\;st %#r0,%1\";
+;      return \"%v0st\\t %#r0,%0\;st %#r0,%1\";
 ;    }
 ;}")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
        (const_int 0))]
   ""
-  "or %0,%#r0,0\;or %d0,%#r0,0"
-  [(set_attr "type" "marith")])
+  "@
+   or %0,%#r0,0\;or %d0,%#r0,0
+   mov %0,%#x0"
+  [(set_attr "type" "marith,mov")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
-       (match_operand:DF 1 "nonimmediate_operand" "r,m,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,x,r,x,x,m")
+       (match_operand:DF 1 "nonimmediate_operand" "r,m,r,r,x,x,m,x"))]
   ""
   "@
    or %0,%#r0,%1\;or %d0,%#r0,%d1
-   ld.d %0,%1
-   st.d %1,%0"
-  [(set_attr "type" "marith,load,store")])
+   %V1ld.d\\t %0,%1
+   %v0st.d\\t %1,%0
+   mov.d %0,%1
+   mov.d %0,%1
+   mov %0,%1
+   %V1ld.d\\t %0,%1
+   %v0st.d\\t %1,%0"
+  [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=r")
   ""
   "
 {
-  if (emit_move_sequence (operands, SFmode))
+  if (emit_move_sequence (operands, SFmode, 0))
     DONE;
 }")
 
 ;; @@ What happens to fconst0_rtx?
 (define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=r")
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
        (const_int 0))]
   ""
-  "or %0,%#r0,0")
+  "@
+   or %0,%#r0,0
+   mov %0,%#x0"
+  [(set_attr "type" "arith,mov")])
 
 (define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
-       (match_operand:SF 1 "nonimmediate_operand" "r,m,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,x,r,x,x,m")
+       (match_operand:SF 1 "nonimmediate_operand" "r,m,r,r,x,x,m,x"))]
   ""
   "@
    or %0,%#r0,%1
-   ld %0,%1
-   st %r1,%0"
-  [(set_attr "type" "arith,load,store")])
+   %V1ld\\t %0,%1
+   %v0st\\t %r1,%0
+   mov.s %0,%1
+   mov.s %0,%1
+   mov %0,%1
+   %V1ld\\t %0,%1
+   %v0st\\t %r1,%0"
+  [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")])
 
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=r")
 ;; String/block move insn.  See m88k.c for details.
 
 (define_expand "movstrsi"
-  [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
-                  (mem:BLK (match_operand:BLK 1 "general_operand" "")))
+  [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
+                  (mem:BLK (match_operand:BLK 1 "" "")))
              (use (match_operand:SI 2 "arith32_operand" ""))
              (use (match_operand:SI 3 "immediate_operand" ""))])]
   ""
   DONE;
 }")
 
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (match_operand:BLK 1 "memory_operand" "m"))]
+  ""
+  "%V1ld.bu\\t %0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (match_operand:BLK 1 "memory_operand" "m"))]
+  ""
+  "%V1ld.hu\\t %0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (match_operand:BLK 1 "memory_operand" "m"))]
+  ""
+  "%V1ld\\t %0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (match_operand:BLK 1 "memory_operand" "m"))]
+  ""
+  "%V1ld.d\\t %0,%1"
+  [(set_attr "type" "loadd")])
+
+(define_insn ""
+  [(set (match_operand:BLK 0 "memory_operand" "=m")
+       (match_operand:QI 1 "register_operand" "r"))]
+  ""
+  "%v0st.b\\t %1,%0"
+  [(set_attr "type" "store")])
+
+(define_insn ""
+  [(set (match_operand:BLK 0 "memory_operand" "=m")
+       (match_operand:HI 1 "register_operand" "r"))]
+  ""
+  "%v0st.h\\t %1,%0"
+  [(set_attr "type" "store")])
+
+(define_insn ""
+  [(set (match_operand:BLK 0 "memory_operand" "=m")
+       (match_operand:SI 1 "register_operand" "r"))]
+  ""
+  "%v0st\\t %1,%0"
+  [(set_attr "type" "store")])
+
+(define_insn ""
+  [(set (match_operand:BLK 0 "memory_operand" "=m")
+       (match_operand:DI 1 "register_operand" "r"))]
+  ""
+  "%v0st.d\\t %1,%0"
+  [(set_attr "type" "store")])
+
 ;; Call a non-looping block move library function (e.g. __movstrSI96x64).
 ;; operand 0 is the function name
 ;; operand 1 is the destination pointer
 ;; operand 3 is the offset for the source and destination pointers
 ;; operand 4 is the first value to be loaded
 ;; operand 5 is the register to hold the value (r4 or r5)
-;; Upon completion, r2 and r3 are unchanged
 
 (define_expand "call_block_move"
-  [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r")
-                            (match_operand:SI 3 "immediate_operand" "i")))
-   (set (match_operand 5 "register_operand" "r")
-       (match_operand 4 "memory_operand" "m"))
-   (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r")
+  [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "")
+                            (match_operand:SI 3 "immediate_operand" "")))
+   (set (match_operand 5 "register_operand" "")
+       (match_operand 4 "memory_operand" ""))
+   (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "")
                             (match_dup 3)))
    (use (reg:SI 2))
    (use (reg:SI 3))
-   (use (reg:SI 4))
-   (use (reg:SI 5))
-   (parallel [(call (mem:SI (match_operand 0 "" ""))
-                   (const_int 0))
-             (use (reg:SI 1))])
-   (clobber (reg:SI 4))
-   (clobber (reg:SI 5))]
+   (use (match_dup 5))
+   (parallel [(set (reg:DI 2)
+                  (call (mem:SI (match_operand 0 "" ""))
+                        (const_int 0)))
+             (clobber (reg:SI 1))])]
   ""
   "")
 
-;; Call a looping block move library function (e.g. __movstrSI64n68).
+;; Call an SImode looping block move library function (e.g. __movstrSI64n68).
 ;; operands 0-5 as in the non-looping interface
 ;; operand 6 is the loop count
 
-(define_expand "call_block_move_loop"
-  [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r")
-                            (match_operand:SI 3 "immediate_operand" "i")))
-   (set (match_operand:SI 5 "register_operand" "r")
-       (match_operand:SI 4 "memory_operand" "m"))
-   (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r")
+(define_expand "call_movstrsi_loop"
+  [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "")
+                            (match_operand:SI 3 "immediate_operand" "")))
+   (set (match_operand:SI 5 "register_operand" "")
+       (match_operand 4 "memory_operand" ""))
+   (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "")
                             (match_dup 3)))
-   (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "i"))
+   (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" ""))
    (use (reg:SI 2))
    (use (reg:SI 3))
-   (use (reg:SI 4))
-   (use (reg:SI 5))
+   (use (match_dup 5))
    (use (reg:SI 6))
-   (parallel [(call (mem:SI (match_operand 0 "" ""))
-                   (const_int 0))
-             (use (reg:SI 1))])
-   (clobber (reg:SI 4))
-   (clobber (reg:SI 5))
-   (clobber (reg:SI 6))]
+   (parallel [(set (reg:DI 2)
+                  (call (mem:SI (match_operand 0 "" ""))
+                        (const_int 0)))
+             (clobber (reg:SI 1))])]
   ""
   "")
 \f
   if (GET_CODE (operands[1]) == MEM
       && symbolic_address_p (XEXP (operands[1], 0)))
     operands[1]
-      = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
+      = legitimize_address (flag_pic, operands[1], 0, 0);
 }")
 
 (define_insn ""
   "@
    mask %0,%1,0xffff
    or %0,%#r0,%h1
-   ld.hu %0,%1"
+   %V1ld.hu\\t %0,%1"
   [(set_attr "type" "arith,arith,load")])
 
 (define_expand "zero_extendqihi2"
   if (GET_CODE (operands[1]) == MEM
       && symbolic_address_p (XEXP (operands[1], 0)))
     operands[1]
-      = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
+      = legitimize_address (flag_pic, operands[1], 0, 0);
 }")
 
 (define_insn ""
   "@
    mask %0,%1,0xff
    or %0,%#r0,%q1
-   ld.bu %0,%1"
+   %V1ld.bu\\t %0,%1"
   [(set_attr "type" "arith,arith,load")])
 
 (define_expand "zero_extendqisi2"
       && symbolic_address_p (XEXP (operands[1], 0)))
     {
       operands[1]
-       = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
+       = legitimize_address (flag_pic, operands[1], 0, 0);
       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
                          gen_rtx (ZERO_EXTEND, SImode, operands[1])));
       DONE;
   "@
    mask %0,%1,0xff
    or %0,%#r0,%q1
-   ld.bu %0,%1"
+   %V1ld.bu\\t %0,%1"
   [(set_attr "type" "arith,arith,load")])
 \f
 ;;- sign extension instructions
   if (GET_CODE (operands[1]) == MEM
       && symbolic_address_p (XEXP (operands[1], 0)))
     operands[1]
-      = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
+      = legitimize_address (flag_pic, operands[1], 0, 0);
 }")
 
 (define_insn ""
    ext %0,%1,16<0>
    or %0,%#r0,%h1
    subu %0,%#r0,%H1
-   ld.h %0,%1"
-  [(set_attr "type" "arith,arith,arith,load")])
+   %V1ld.h\\t %0,%1"
+  [(set_attr "type" "bit,arith,arith,load")])
 
 (define_expand "extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "")
   if (GET_CODE (operands[1]) == MEM
       && symbolic_address_p (XEXP (operands[1], 0)))
     operands[1]
-      = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
+      = legitimize_address (flag_pic, operands[1], 0, 0);
 }")
 
 (define_insn ""
    ext %0,%1,8<0>
    or %0,%#r0,%q1
    subu %0,%#r0,%Q1
-   ld.b %0,%1"
-  [(set_attr "type" "arith,arith,arith,load")])
+   %V1ld.b\\t %0,%1"
+  [(set_attr "type" "bit,arith,arith,load")])
 
 (define_expand "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "")
   if (GET_CODE (operands[1]) == MEM
       && symbolic_address_p (XEXP (operands[1], 0)))
     operands[1]
-      = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
+      = legitimize_address (flag_pic, operands[1], 0, 0);
 }")
 
 (define_insn ""
    ext %0,%1,8<0>
    or %0,%#r0,%q1
    subu %0,%#r0,%Q1
-   ld.b %0,%1"
-  [(set_attr "type" "arith,arith,arith,load")])
+   %V1ld.b\\t %0,%1"
+  [(set_attr "type" "bit,arith,arith,load")])
 \f
 ;; Conversions between float and double.
 
 ;; convert between float and double.  In particular, the sign of -0 is
 ;; not preserved.  Interestingly, fsub does conform.
 
-(define_insn "extendsfdf2"
+(define_expand "extendsfdf2"
   [(set (match_operand:DF 0 "register_operand" "=r")
        (float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
   ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=r")
+       (float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
+  "! TARGET_88110"
   "fsub.dss %0,%1,%#r0"
   [(set_attr "type" "spadd")])
 
-(define_insn "truncdfsf2"
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")))]
+  "TARGET_88110"
+  "fcvt.ds %0,%1"
+  [(set_attr "type" "spadd")])
+
+(define_expand "truncdfsf2"
   [(set (match_operand:SF 0 "register_operand" "=r")
        (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
   ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=r")
+       (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
+  "! TARGET_88110"
   "fsub.sds %0,%1,%#r0"
   [(set_attr "type" "dpadd")])
 
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (float_truncate:SF (match_operand:DF 1 "register_operand" "r,x")))]
+  "TARGET_88110"
+  "fcvt.sd %0,%1"
+  [(set_attr "type" "dpadd")])
+
 ;; Conversions between floating point and integer
 
 (define_insn "floatsidf2"
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (float:DF (match_operand:SI 1 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (float:DF (match_operand:SI 1 "register_operand" "r,r")))]
   ""
   "flt.ds %0,%1"
-  [(set_attr "type" "spadd")])
+  [(set_attr "type" "spadd,dpadd")])
 
 (define_insn "floatsisf2"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-       (float:SF (match_operand:SI 1 "register_operand" "r")))]
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (float:SF (match_operand:SI 1 "register_operand" "r,r")))]
   ""
   "flt.ss %0,%1"
-  [(set_attr "type" "spadd")])
+  [(set_attr "type" "spadd,spadd")])
 
 (define_insn "fix_truncdfsi2"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (fix:SI (match_operand:DF 1 "register_operand" "r")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (fix:SI (match_operand:DF 1 "register_operand" "r,x")))]
   ""
   "trnc.sd %0,%1"
-  [(set_attr "type" "dpadd")])
+  [(set_attr "type" "dpadd,dpadd")])
 
 (define_insn "fix_truncsfsi2"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (fix:SI (match_operand:SF 1 "register_operand" "r")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (fix:SI (match_operand:SF 1 "register_operand" "r,x")))]
   ""
   "trnc.ss %0,%1"
-  [(set_attr "type" "spadd")])
+  [(set_attr "type" "spadd,dpadd")])
 
 \f
 ;;- arithmetic instructions
    addu %0,%1,%2
    subu %0,%1,%n2")
 
-;; In unusual contexts, an add of a large value is generated (case statements
-;; for example).  In these contexts, it is sufficient to accept only those
-;; cases where the two registers are different.
-
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r,&r")
-       (plus:SI (match_operand:SI 1 "arith32_operand" "%r,r")
-                (match_operand:SI 2 "arith32_operand" "r,!n")))]
-  ""
-  "*
-{
-  rtx xoperands[10];
-
-  if (which_alternative == 0)
-    return \"addu %0,%1,%2\";
-
-  xoperands[0] = operands[0];
-  xoperands[1] = operands[2];
-  output_asm_insn (output_load_const_int (SImode, xoperands),
-                  xoperands);
-
-  return \"addu %0,%1,%0\";
-}"
-  [(set_attr "type" "arith,marith")
-   (set_attr "length" "1,3")]) ; may be 2 or 3.
-
 ;; patterns for mixed mode floating point.
 ;; Do not define patterns that utilize mixed mode arithmetic that result
 ;; in narrowing the precision, because it loses accuracy, since the standard
 ;; requires double rounding, whereas the 88000 instruction only rounds once.
 
 (define_expand "adddf3"
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (plus:DF (match_operand:DF 1 "general_operand" "%r")
-                (match_operand:DF 2 "general_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (plus:DF (match_operand:DF 1 "general_operand" "%r,x")
+                (match_operand:DF 2 "general_operand" "r,x")))]
   ""
   "
 {
 }")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-                (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+                (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fadd.dss %0,%1,%2"
   [(set_attr "type" "spadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (plus:DF (match_operand:DF 1 "register_operand" "r")
-                (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (plus:DF (match_operand:DF 1 "register_operand" "r,x")
+                (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fadd.dds %0,%1,%2"
   [(set_attr "type" "dpadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-                (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+                (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fadd.dsd %0,%1,%2"
   [(set_attr "type" "dpadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (plus:DF (match_operand:DF 1 "register_operand" "%r")
-                (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (plus:DF (match_operand:DF 1 "register_operand" "%r,x")
+                (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fadd.ddd %0,%1,%2"
   [(set_attr "type" "dpadd")])
 
 (define_insn "addsf3"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-       (plus:SF (match_operand:SF 1 "register_operand" "%r")
-                (match_operand:SF 2 "register_operand" "r")))]
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (plus:SF (match_operand:SF 1 "register_operand" "%r,x")
+                (match_operand:SF 2 "register_operand" "r,x")))]
   ""
   "fadd.sss %0,%1,%2"
   [(set_attr "type" "spadd")])
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "register_operand" "r")
                 (zero_extend:DI
-                 (match_operand:SI 2 "register_operand" "r"))))]
+                 (match_operand:SI 2 "register_operand" "r"))))
+   (clobber (reg:CC 0))]
   ""
   "addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0"
   [(set_attr "type" "marith")])
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (zero_extend:DI
                  (match_operand:SI 1 "register_operand" "r"))
-                (match_operand:DI 2 "register_operand" "r")))]
+                (match_operand:DI 2 "register_operand" "r")))
+   (clobber (reg:CC 0))]
   ""
   "addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2"
   [(set_attr "type" "marith")])
 (define_insn "adddi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "register_operand" "%r")
-                (match_operand:DI 2 "register_operand" "r")))]
+                (match_operand:DI 2 "register_operand" "r")))
+   (clobber (reg:CC 0))]
   ""
   "addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2"
   [(set_attr "type" "marith")])
+
+;; Add with carry insns.
+
+(define_insn ""
+  [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+                  (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+                           (match_operand:SI 2 "reg_or_0_operand" "rO")))
+             (set (reg:CC 0)
+                  (unspec:CC [(match_dup 1) (match_dup 2)] 0))])]
+  ""
+  "addu.co %r0,%r1,%r2")
+
+(define_insn ""
+  [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO")
+                              (match_operand:SI 1 "reg_or_0_operand" "rO")]
+                             0))]
+  ""
+  "addu.co %#r0,%r0,%r1")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+       (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+                (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO")
+                            (reg:CC 0)] 0)))]
+  ""
+  "addu.ci %r0,%r1,%r2")
 \f
 ;;- subtract instructions
 
 ;; requires double rounding, whereas the 88000 instruction only rounds once.
 
 (define_expand "subdf3"
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (minus:DF (match_operand:DF 1 "general_operand" "r")
-                 (match_operand:DF 2 "general_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (minus:DF (match_operand:DF 1 "general_operand" "r,x")
+                 (match_operand:DF 2 "general_operand" "r,x")))]
   ""
   "
 {
 }")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-                 (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+                 (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fsub.dss %0,%1,%2"
   [(set_attr "type" "spadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (minus:DF (match_operand:DF 1 "register_operand" "r")
-                 (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (minus:DF (match_operand:DF 1 "register_operand" "r,x")
+                 (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fsub.dds %0,%1,%2"
   [(set_attr "type" "dpadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-                 (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+                 (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fsub.dsd %0,%1,%2"
   [(set_attr "type" "dpadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (minus:DF (match_operand:DF 1 "register_operand" "r")
-                 (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (minus:DF (match_operand:DF 1 "register_operand" "r,x")
+                 (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fsub.ddd %0,%1,%2"
   [(set_attr "type" "dpadd")])
 
 (define_insn "subsf3"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-       (minus:SF (match_operand:SF 1 "register_operand" "r")
-                 (match_operand:SF 2 "register_operand" "r")))]
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (minus:SF (match_operand:SF 1 "register_operand" "r,x")
+                 (match_operand:SF 2 "register_operand" "r,x")))]
   ""
   "fsub.sss %0,%1,%2"
   [(set_attr "type" "spadd")])
   [(set (match_operand:DI 0 "register_operand" "=r")
        (minus:DI (match_operand:DI 1 "register_operand" "r")
                  (zero_extend:DI
-                  (match_operand:SI 2 "register_operand" "r"))))]
+                  (match_operand:SI 2 "register_operand" "r"))))
+   (clobber (reg:CC 0))]
   ""
   "subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0"
   [(set_attr "type" "marith")])
   [(set (match_operand:DI 0 "register_operand" "=r")
        (minus:DI (zero_extend:DI
                   (match_operand:SI 1 "register_operand" "r"))
-                 (match_operand:DI 2 "register_operand" "r")))]
+                 (match_operand:DI 2 "register_operand" "r")))
+   (clobber (reg:CC 0))]
   ""
   "subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2"
   [(set_attr "type" "marith")])
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (minus:DI (match_operand:DI 1 "register_operand" "r")
-                 (match_operand:DI 2 "register_operand" "r")))]
+                 (match_operand:DI 2 "register_operand" "r")))
+   (clobber (reg:CC 0))]
   ""
   "subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2"
   [(set_attr "type" "marith")])
+
+;; Subtract with carry insns.
+
+(define_insn ""
+  [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+                  (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+                            (match_operand:SI 2 "reg_or_0_operand" "rO")))
+             (set (reg:CC 0)
+                  (unspec:CC [(match_dup 1) (match_dup 2)] 1))])]
+  ""
+  "subu.co %r0,%r1,%r2")
+
+(define_insn ""
+  [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO")
+                              (match_operand:SI 1 "reg_or_0_operand" "rO")]
+                             1))]
+  ""
+  "subu.co %#r0,%r0,%r1")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+       (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+                 (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO")
+                             (reg:CC 0)] 1)))]
+  ""
+  "subu.ci %r0,%r1,%r2")
 \f
 ;;- multiply instructions
 ;;
-;; There is an unfounded silicon eratta for E.1 requiring that an
+;; There is an unfounded silicon errata for E.1 requiring that an
 ;; immediate constant value in div/divu/mul instructions be less than
 ;; 0x800.  This is no longer provided for.
 
   "mul %0,%1,%2"
   [(set_attr "type" "imul")])
 
+(define_insn "umulsidi3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
+                 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+  "TARGET_88110"
+  "mulu.d %0,%1,%2"
+  [(set_attr "type" "imul")])
+
 ;; patterns for mixed mode floating point
 ;; Do not define patterns that utilize mixed mode arithmetic that result
 ;; in narrowing the precision, because it loses accuracy, since the standard
 ;; requires double rounding, whereas the 88000 instruction only rounds once.
 
 (define_expand "muldf3"
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (mult:DF (match_operand:DF 1 "general_operand" "%r")
-                (match_operand:DF 2 "general_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (mult:DF (match_operand:DF 1 "general_operand" "%r,x")
+                (match_operand:DF 2 "general_operand" "r,x")))]
   ""
   "
 {
 }")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-                (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+                (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fmul.dss %0,%1,%2"
   [(set_attr "type" "spmul")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (mult:DF (match_operand:DF 1 "register_operand" "r")
-                (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (mult:DF (match_operand:DF 1 "register_operand" "r,x")
+                (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fmul.dds %0,%1,%2"
   [(set_attr "type" "spmul")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-                (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+                (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fmul.dsd %0,%1,%2"
   [(set_attr "type" "spmul")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (mult:DF (match_operand:DF 1 "register_operand" "%r")
-                (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (mult:DF (match_operand:DF 1 "register_operand" "%r,x")
+                (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fmul.ddd %0,%1,%2"
   [(set_attr "type" "dpmul")])
 
 (define_insn "mulsf3"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-       (mult:SF (match_operand:SF 1 "register_operand" "%r")
-                (match_operand:SF 2 "register_operand" "r")))]
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (mult:SF (match_operand:SF 1 "register_operand" "%r,x")
+                (match_operand:SF 2 "register_operand" "r,x")))]
   ""
   "fmul.sss %0,%1,%2"
   [(set_attr "type" "spmul")])
 ;; for divide-by-zero or take your chances.  If the div instruction is
 ;; used, the O/S must complete the operation if the operands are
 ;; negative.  The O/S will signal an overflow condition if the most
-;; negative number (-214783648) is divided by negative 1.
+;; negative number (-2147483648) is divided by negative 1.
 ;;
-;; There is an unfounded silicon eratta for E.1 requiring that an
+;; There is an unfounded silicon errata for E.1 requiring that an
 ;; immediate constant value in div/divu/mul instructions be less than
 ;; 0x800.  This is no longer provided for.
 
   emit_insn (gen_cmpsi (operands[0], const0_rtx));
   emit_jump_insn (gen_bne (operands[1]));
   emit_insn (gen_trap_divide_by_zero ());
-  emit_barrier ();
   DONE;
 }")
 
   if (op2 == const0_rtx)
     {
       emit_insn (gen_trap_divide_by_zero ());
-      emit_barrier ();
       emit_insn (gen_dummy (op0));
       DONE;
     }
 
       if (TARGET_CHECK_ZERO_DIV)
        emit_insn (gen_tcnd_divide_by_zero (op2, join_label));
-      else
-       {
-         emit_jump_insn (gen_jump (join_label));
-         emit_barrier ();
-       }
+      emit_jump_insn (gen_jump (join_label));
+      emit_barrier ();
 
       emit_label (label1);                     /* constant / positive */
       emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2));
          emit_jump_insn (gen_bne (join_label));
          emit_label (label4);
          emit_insn (gen_trap_divide_by_zero ());
-         emit_barrier ();
-       }
-      else
-       {
-         emit_jump_insn (gen_jump (join_label));
-         emit_barrier ();
        }
+      emit_jump_insn (gen_jump (join_label));
+      emit_barrier ();
 
       emit_label (label2);                     /* pos.-or-0 / neg.-or-0 */
       emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2));
   if (op2 == const0_rtx)
     {
       emit_insn (gen_trap_divide_by_zero ());
-      emit_barrier ();
       emit_insn (gen_dummy (operands[0]));
       DONE;
     }
 ;; requires double rounding, whereas the 88000 instruction only rounds once.
 
 (define_expand "divdf3"
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (div:DF (match_operand:DF 1 "general_operand" "r")
-               (match_operand:DF 2 "general_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (div:DF (match_operand:DF 1 "general_operand" "r,x")
+               (match_operand:DF 2 "general_operand" "r,x")))]
   ""
   "
 {
 }")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-               (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+               (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fdiv.dss %0,%1,%2"
   [(set_attr "type" "dpdiv")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (div:DF (match_operand:DF 1 "register_operand" "r")
-               (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (div:DF (match_operand:DF 1 "register_operand" "r,x")
+               (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
   ""
   "fdiv.dds %0,%1,%2"
   [(set_attr "type" "dpdiv")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
-               (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+               (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fdiv.dsd %0,%1,%2"
   [(set_attr "type" "dpdiv")])
 
 (define_insn "divsf3"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-       (div:SF (match_operand:SF 1 "register_operand" "r")
-               (match_operand:SF 2 "register_operand" "r")))]
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (div:SF (match_operand:SF 1 "register_operand" "r,x")
+               (match_operand:SF 2 "register_operand" "r,x")))]
   ""
   "fdiv.sss %0,%1,%2"
   [(set_attr "type" "spdiv")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=r")
-       (div:DF (match_operand:DF 1 "register_operand" "r")
-               (match_operand:DF 2 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=r,x")
+       (div:DF (match_operand:DF 1 "register_operand" "r,x")
+               (match_operand:DF 2 "register_operand" "r,x")))]
   ""
   "fdiv.ddd %0,%1,%2"
   [(set_attr "type" "dpdiv")])
    or.u %0,%1,%X2
    set %0,%1,%s2
    or.u %0,%1,%X2\;or %0,%0,%x2"
-  [(set_attr "type" "arith,arith,arith,marith")])
+  [(set_attr "type" "arith,arith,bit,marith")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
                     (const_int 24)))]
   "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
-  "ld.b %0,%1"
+  "%V1ld.b\\t %0,%1"
   [(set_attr "type" "load")])
 
 (define_insn ""
        (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
                     (const_int 24)))]
   "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
-  "ld.bu %0,%1"
+  "%V1ld.bu\\t %0,%1"
   [(set_attr "type" "load")])
 
 (define_insn ""
        (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
                     (const_int 16)))]
   "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
-  "ld.h %0,%1"
+  "%V1ld.h\\t %0,%1"
   [(set_attr "type" "load")])
 
 (define_insn ""
        (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
                     (const_int 16)))]
   "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
-  "ld.hu %0,%1"
+  "%V1ld.hu\\t %0,%1"
   [(set_attr "type" "load")])
 \f
 ;;- arithmetic shift instructions.
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
-                  (match_operand:SI 2 "arith5_operand" "r,n")))]
+                  (match_operand:SI 2 "arith5_operand" "r,K")))]
   ""
   "@
    mak %0,%1,%2
-   mak %0,%1,0<%2>")
+   mak %0,%1,0<%2>"
+  [(set_attr "type" "bit")])
 
 (define_expand "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "")
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
-                    (match_operand:SI 2 "arith5_operand" "r,n")))]
+                    (match_operand:SI 2 "arith5_operand" "r,K")))]
   ""
   "@
    ext %0,%1,%2
-   ext %0,%1,0<%2>")
+   ext %0,%1,0<%2>"
+  [(set_attr "type" "bit")])
 \f
 ;;- logical shift instructions.  Logical shift left becomes arithmetic
-;; shift left.  LSHIFT is not normally produced, but is supported.
-
-(define_expand "lshlsi3"
-  [(set (match_operand:SI 0 "register_operand" "")
-       (lshift:SI (match_operand:SI 1 "register_operand" "")
-                  (match_operand:SI 2 "arith32_operand" "")))]
-  ""
-  "
-{
-  emit_insn (gen_ashlsi3 (operands[0], operands[1], operands[2]));
-  DONE;
-}")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (lshift:SI (match_operand:SI 1 "register_operand" "r,r")
-                  (match_operand:SI 2 "arith5_operand" "r,n")))]
-  ""
-  "@
-   mak %0,%1,%2
-   mak %0,%1,0<%2>")
+;; shift left.  
 
 (define_expand "lshrsi3"
   [(set (match_operand:SI 0 "register_operand" "")
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
-                    (match_operand:SI 2 "arith5_operand" "r,n")))]
+                    (match_operand:SI 2 "arith5_operand" "r,K")))]
   ""
   "@
    extu %0,%1,%2
-   extu %0,%1,0<%2>")
+   extu %0,%1,0<%2>"
+  [(set_attr "type" "bit")])
 \f
 ;;- rotate instructions
 
        (rotatert:SI (match_operand:SI 1 "register_operand" "r")
                     (match_operand:SI 2 "arith_operand" "rI")))]
   ""
-  "rot %0,%1,%2")
+  "rot %0,%1,%2"
+  [(set_attr "type" "bit")])
+\f
+;; find first set.
+
+;; The ff1 instruction searches from the most significant bit while ffs
+;; searches from the least significant bit.  The bit index and treatment of
+;; zero also differ.  This amazing sequence was discovered using the GNU
+;; Superoptimizer.
+
+(define_insn "ffssi2"
+  [(set (match_operand:SI 0 "register_operand" "=r,&r")
+       (ffs:SI (match_operand:SI 1 "register_operand" "0,r")))
+   (clobber (reg:CC 0))
+   (clobber (match_scratch:SI 2 "=r,X"))]
+  ""
+  "@
+   subu.co %2,%#r0,%1\;and %2,%2,%1\;addu.ci %2,%2,%2\;ff1 %0,%2
+   subu.co %0,%#r0,%1\;and %0,%0,%1\;addu.ci %0,%0,%0\;ff1 %0,%0"
+  [(set_attr "type" "marith")
+   (set_attr "length" "4")])
 \f
 ;; Bit field instructions.
 
   operands[4] = gen_rtx (CONST_INT, SImode,
                         (32 - INTVAL (operands[2])) - INTVAL (operands[3]));
   return \"ext %0,%1,%2<%4>\";  /* <(32-%2-%3)> */
-}")
+}"
+  [(set_attr "type" "bit")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
   operands[4] = gen_rtx (CONST_INT, SImode,
                         (32 - INTVAL (operands[2])) - INTVAL (operands[3]));
   return \"extu %0,%1,%2<%4>\";  /* <(32-%2-%3)> */
-}")
+}"
+  [(set_attr "type" "bit")])
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
                         (match_operand:SI 1 "int5_operand" "")
                         (match_operand:SI 2 "int5_operand" ""))
        (const_int 0))]
   operands[3] = gen_rtx (CONST_INT, SImode,
                         (32 - INTVAL (operands[1])) - INTVAL (operands[2]));
   return \"clr %0,%0,%1<%3>\";  /* <(32-%1-%2)> */
-}")
+}"
+  [(set_attr "type" "bit")])
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
                         (match_operand:SI 1 "int5_operand" "")
                         (match_operand:SI 2 "int5_operand" ""))
        (const_int -1))]
   operands[3] = gen_rtx (CONST_INT, SImode,
                         (32 - INTVAL (operands[1])) - INTVAL (operands[2]));
   return \"set %0,%0,%1<%3>\";  /* <(32-%1-%2)> */
-}")
+}"
+  [(set_attr "type" "bit")])
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=r")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
                         (match_operand:SI 1 "int5_operand" "")
                         (match_operand:SI 2 "int5_operand" ""))
        (match_operand:SI 3 "int32_operand" "n"))]
   "subu %0,%#r0,%1")
 
 (define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=r")
-       (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r"))))]
+  [(set (match_operand:SF 0 "register_operand" "=r,x")
+       (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r,x"))))]
   ""
-  "fsub.ssd %0,%#r0,%1"
+  "@
+   fsub.ssd %0,%#r0,%1
+   fsub.ssd %0,%#x0,%1"
   [(set_attr "type" "dpadd")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "+r")
-       (neg:DF (match_dup 0)))]
-  ""
-  "xor.u %0,%0,0x8000")
-
 (define_insn "negdf2"
-  [(set (match_operand:DF 0 "register_operand" "=&r")
-       (neg:DF (match_operand:DF 1 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=&r,r")
+       (neg:DF (match_operand:DF 1 "register_operand" "r,0")))]
   ""
-  "xor.u %0,%1,0x8000\;or %d0,%#r0,%d1"
-  [(set_attr "type" "marith")])
+  "@
+   xor.u %0,%1,0x8000\;or %d0,%#r0,%d1
+   xor.u %0,%0,0x8000"
+  [(set_attr "type" "marith,arith")])
 
 (define_insn "negsf2"
   [(set (match_operand:SF 0 "register_operand" "=r")
 ;; absolute value insns for floating-point (integer abs can be done using the
 ;; machine-independent sequence).
 
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "+r")
-       (abs:DF (match_dup 0)))]
-  ""
-  "and.u %0,%0,0x7fff")
-
 (define_insn "absdf2"
-  [(set (match_operand:DF 0 "register_operand" "=&r")
-       (abs:DF (match_operand:DF 1 "register_operand" "r")))]
+  [(set (match_operand:DF 0 "register_operand" "=&r,r")
+       (abs:DF (match_operand:DF 1 "register_operand" "r,0")))]
   ""
-  "and.u %0,%1,0x7fff\;or %d0,%#r0,%d1"
-  [(set_attr "type" "marith")])
+  "@
+   and.u %0,%1,0x7fff\;or %d0,%#r0,%d1
+   and.u %0,%0,0x7fff"
+  [(set_attr "type" "marith,arith")])
 
 (define_insn "abssf2"
   [(set (match_operand:SF 0 "register_operand" "=r")
 {
   register rtx index_diff = gen_reg_rtx (SImode);
   register rtx low = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1]));
+  register rtx label = gen_rtx (LABEL_REF, VOIDmode, operands[3]);
+  register rtx base;
+
+  if (! CASE_VECTOR_INSNS)
+    /* These instructions are likely to be scheduled and made loop invariant.
+       This decreases the cost of the dispatch at the expense of the default
+       case.  */
+    base = force_reg (SImode, memory_address_noforce (SImode, label));
 
   /* Compute the index difference and handle the default case.  */
   emit_insn (gen_addsi3 (index_diff,
                         force_reg (SImode, operands[0]),
                         ADD_INT (low) ? low : force_reg (SImode, low)));
   emit_insn (gen_cmpsi (index_diff, operands[2]));
+  /* It's possible to replace this branch with sgtu/iorsi3 and adding a -1
+     entry to the table.  However, that doesn't seem to win on the m88110.  */
   emit_jump_insn (gen_bgtu (operands[4]));
 
-  /* Call the jump that will branch to the appropriate case.  */
-  emit_jump_insn (gen_casesi_enter (gen_rtx (LABEL_REF, VOIDmode, operands[3]),
-                                   index_diff,
-                                   operands[3]));
-  /* Claim that flow drops into the table so it will be adjacent.  */
+  if (CASE_VECTOR_INSNS)
+    /* Call the jump that will branch to the appropriate case.  */
+    emit_jump_insn (gen_casesi_enter (label, index_diff, operands[3]));
+  else
+    /* Load the table entry and jump to it.  */
+    emit_jump_insn (gen_casesi_jump (gen_reg_rtx (SImode), base, index_diff, operands[3]));
+
+  /* Claim that flow drops into the table so it will be adjacent by not
+     emitting a barrier.  */
   DONE;
 }")
 
+(define_expand "casesi_jump"
+  [(set (match_operand:SI 0 "" "")
+       (mem:SI (plus:SI (match_operand:SI 1 "" "")
+                        (mult:SI (match_operand:SI 2 "" "")
+                                 (const_int 4)))))
+   (parallel [(set (pc) (match_dup 0))
+              (use (label_ref (match_operand 3 "" "")))])]
+  ""
+  "")
+
+(define_insn ""
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "jmp%. %0"
+  [(set_attr "type" "jump")])
+
 ;; The bsr.n instruction is directed to the END of the table.  See
 ;; ASM_OUTPUT_CASE_END.
 
 (define_expand "call"
   [(parallel [(call (match_operand:SI 0 "" "")
                    (match_operand 1 "" ""))
-             (use (reg:SI 1))])]
+             (clobber (reg:SI 1))])]
   ""
   "
 {
 (define_insn ""
   [(parallel [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rQ"))
                    (match_operand 1 "" ""))
-             (use (reg:SI 1))])]
+             (clobber (reg:SI 1))])]
   ""
   "* return output_call (operands, operands[0]);"
   [(set_attr "type" "call")])
   [(parallel [(set (match_operand 0 "register_operand" "")
                   (call (match_operand:SI 1 "" "")
                         (match_operand 2 "" "")))
-             (use (reg:SI 1))])]
+             (clobber (reg:SI 1))])]
   ""
   "
 {
                   (call (mem:SI
                          (match_operand:SI 1 "call_address_operand" "rQ"))
                         (match_operand 2 "" "")))
-             (use (reg:SI 1))])]
+             (clobber (reg:SI 1))])]
   ""
   "* return output_call (operands, operands[1]);"
   [(set_attr "type" "call")])
 (define_insn "nop"
   [(const_int 0)]
   ""
-  "ff0 %#r0,%#r0")
+  "ff0 %#r0,%#r0"
+  [(set_attr "type" "bit")])
 
 (define_insn "return"
   [(return)]
-  "null_epilogue ()"
+  "reload_completed"
   "jmp%. %#r1"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "jump")])
+
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "m88k_expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+  [(return)]
+  "! null_prologue ()"
+  "m88k_expand_epilogue ();")
+
+(define_insn "blockage"
+  [(unspec_volatile [(const_int 0)] 0)]
+  ""
+  ""
+  [(set_attr "length" "0")])
 
 (define_insn "indirect_jump"
   [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
   ""
   "jmp%. %0"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "jump")])
 
 (define_insn "jump"
   [(set (pc)
 ;; reloads, hence the `m' constraints.  The `!' constraints direct reload
 ;; to not choose the register alternatives in the event a reload is needed.
 
-(define_insn "decrement_and_branch_until_zero"
+(define_expand "decrement_and_branch_until_zero"
+  [(parallel [(set (pc)
+                  (if_then_else
+                   (match_operator 0 "relop_no_unsigned"
+                                   [(match_operand:SI 1 "register_operand" "")
+                                    (const_int 0)])
+                   (label_ref (match_operand 2 "" ""))
+                   (pc)))
+             (set (match_dup 1)
+                  (plus:SI (match_dup 1)
+                           (match_operand:SI 3 "add_operand" "")))
+             (clobber (match_scratch:SI 4 ""))
+             (clobber (match_scratch:SI 5 "=X,X,&r,&r"))])]
+  ""
+  "")
+
+(define_insn ""
   [(set (pc)
        (if_then_else
         (match_operator 0 "relop_no_unsigned"
   [(set (match_operand 0 "" "") (match_dup 0))]
   ""
   "")
-\f
-;;- Local variables:
-;;- mode:emacs-lisp
-;;- comment-start: ";;- "
-;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
-;;- eval: (modify-syntax-entry ?[ "(]")
-;;- eval: (modify-syntax-entry ?] ")[")
-;;- eval: (modify-syntax-entry ?{ "(}")
-;;- eval: (modify-syntax-entry ?} "){")
-;;- End: