OSDN Git Service

(blockage insn): Renamed from profiler.
authorwood <wood@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 2 Jul 1992 10:29:02 +0000 (10:29 +0000)
committerwood <wood@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 2 Jul 1992 10:29:02 +0000 (10:29 +0000)
(epilogue insn): Don't provide this if a return insn will suffice.
(m88k_end_epilogue): If the last insn isn't a barrier, print a return.
(compare word insns): New insns and define_split
patterns to take advantage of recent fold_truthop change.
(superoptimizer sequences): New define_split patterns.
(add/sub with carry): New insns.
(add/sub DImode, ffssi2): Clobber the condition code register.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@1383 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/m88k/m88k.md

index db640b4..2efc2f9 100644 (file)
@@ -28,7 +28,7 @@
 (define_expand "m88k_sccs_id"
   [(match_operand:SI 0 "" "")]
   ""
-  "{ static char sccs_id[] = \"@(#)m88k.md     2.2.3.13 29 Jun 1992 16:41:06\";
+  "{ static char sccs_id[] = \"@(#)m88k.md     2.2.6.5 01 Jul 1992 18:47:08\";
      FAIL; }")
 \f
 ;; Attribute specifications
 ;(define_function_unit "writeback" 1 1 (eq_attr "type" "store") 0 1)
 ;(define_function_unit "memory" 1 3 (eq_attr "type" "store") 1 2)
 \f
+;; Superoptimizer sequences
+
+;; 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)))]
+  "")
+
+;; leu+: { r = ((unsigned_word) v0 <= (unsigned_word) v1) + v2; }
+;;      subu.co r5,r3,r2
+;;      addu.cio r6,r4,r0
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (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)))]
+  "")
+
+;; 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")
+       (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.
 }"
   [(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.
+;;
+;; 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 "relop"
+                                [(match_operand:CC 2 "register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "relop"
+                                [(match_operand:CC 4 "register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (ior:CC (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, CCmode, 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 (match_operator 1 "relop"
+                               [(match_operand:CC 2 "register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "relop"
+                               [(match_operand:CC 4 "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: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, CCmode, 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 (neg:SI 
+                (match_operator 1 "relop"
+                                [(match_operand:CC 2 "register_operand" "%r")
+                                 (const_int 0)]))
+               (neg:SI
+                (match_operator 3 "relop"
+                                [(match_operand:CC 4 "register_operand" "r")
+                                 (const_int 0)]))))
+   (clobber (match_operand:SI 5 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 5)
+       (and:CC (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, CCmode, 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 (match_operator 1 "relop"
+                               [(match_operand:CC 2 "register_operand" "%r")
+                                (const_int 0)])
+               (match_operator 3 "relop"
+                               [(match_operand:CC 4 "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: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, CCmode, 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]);")
+\f
+;; Logical operations on compare words.
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (and:CC (not:CC (match_operand:CC 1 "register_operand" "r"))
+               (match_operand:CC 2 "register_operand" "r")))]
+  ""
+  "and.c %0,%2,%1")
+
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (and:CC (match_operand:CC 1 "register_operand" "%r")
+               (match_operand:CC 2 "register_operand" "r")))]
+  ""
+  "and %0,%1,%2")
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (ior:CC (not:CC (match_operand:CC 1 "register_operand" "r"))
+               (match_operand:CC 2 "register_operand" "r")))]
+  ""
+  "or.c %0,%2,%1")
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (ior:CC (match_operand:CC 1 "register_operand" "%r")
+               (match_operand:CC 2 "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")])
+
+;; rotate/and[.c] and rotate/ior[.c]
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (ior:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_scratch:CC 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (ior:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_operand:CC 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (ior:CC (match_dup 4) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (ior:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_scratch:CC 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (ior:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_operand:CC 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (ior:CC (not:CC (match_dup 4)) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (and:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_scratch:CC 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (and:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                          (match_operand:CC 2 "int5_operand" ""))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_operand:CC 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (ior:CC (match_dup 4) (match_dup 3)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (and:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_scratch:CC 4 "=r"))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:CC 0 "register_operand" "=r")
+       (and:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+                                  (match_operand:CC 2 "int5_operand" "")))
+               (match_operand:CC 3 "register_operand" "r")))
+   (clobber (match_operand:CC 4 "register_operand" "=r"))]
+  ""
+  [(set (match_dup 4)
+       (rotate:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (and:CC (not:CC (match_dup 4)) (match_dup 3)))]
+  "")
+\f
 ;; Recognize bcnd instructions for integer values.  This is distinguished
 ;; from a conditional branch instruction (below) with SImode instead of
 ;; CCmode.
     return \"bb1%. %R3%C0,%1,%P2%P3\";
 }"
   [(set_attr "type" "branch")])
+
+;; Branch conditional on scc values.  These arise from manipulations on
+;; compare words above.
+
+(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" "")))]
+  ""
+  "bb1%. %R3%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" "")))]
+  ""
+  "bb0%. %R3%C0,%1,%P2%P3"
+  [(set_attr "type" "branch")])
 \f
 (define_insn "locate1"
   [(set (match_operand:SI 0 "register_operand" "r")
   [(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
 
   [(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
 ;;
 (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"))]
   ""
   "@
 
 (define_insn "return"
   [(return)]
-  "null_epilogue ()"
+  "null_prologue ()"
   "jmp%. %#r1"
   [(set_attr "type" "jump")])
 
 
 (define_expand "epilogue"
   [(set (pc) (reg:SI 1))]
-  ""
+  "! null_prologue ()"
   "m88k_expand_epilogue ();")
 
-(define_insn "profiler"
+(define_insn "blockage"
   [(unspec_volatile [(const_int 0)] 0)]
   ""
   ""