OSDN Git Service

M68K TLS support.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.md
index 29624a4..037bb37 100644 (file)
@@ -1,6 +1,6 @@
 ;;- Machine description for GNU compiler, Motorola 68000 Version
 ;;  Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001,
-;;  2002, 2003, 2004, 2005, 2006, 2007
+;;  2002, 2003, 2004, 2005, 2006, 2007, 2008
 ;;  Free Software Foundation, Inc.
 
 ;; This file is part of GCC.
    (UNSPEC_GOT 3)
    (UNSPEC_IB 4)
    (UNSPEC_TIE 5)
-   (UNSPEC_GOTOFF 6)
+   (UNSPEC_RELOC16 6)
+   (UNSPEC_RELOC32 7)
   ])
 
 ;; UNSPEC_VOLATILE usage:
 ;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
 ;; be folded while optimizing anyway.
 
-(define_expand "tstdi"
-  [(parallel [(set (cc0)
-                  (match_operand:DI 0 "nonimmediate_operand" ""))
-             (clobber (match_scratch:SI 1 ""))
-             (clobber (match_scratch:DI 2 ""))])]
-  ""
-  "m68k_last_compare_had_fp_operands = 0;")
-
-(define_insn ""
+(define_insn "tstdi"
   [(set (cc0)
-       (match_operand:DI 0 "nonimmediate_operand" "am,d"))
+       (compare (match_operand:DI 0 "nonimmediate_operand" "am,d")
+                (const_int 0)))
    (clobber (match_scratch:SI 1 "=X,d"))
    (clobber (match_scratch:DI 2 "=d,X"))]
   ""
     return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0";
 })
 
-(define_expand "tstsi"
-  [(set (cc0)
-       (match_operand:SI 0 "nonimmediate_operand" ""))]
-  ""
-  "m68k_last_compare_had_fp_operands = 0;")
-
 ;; If you think that the 68020 does not support tstl a0,
 ;; reread page B-167 of the 68020 manual more carefully.
 (define_insn "*tstsi_internal_68020_cf"
   [(set (cc0)
-       (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+       (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
+                (const_int 0)))]
   "TARGET_68020 || TARGET_COLDFIRE"
   "tst%.l %0"
   [(set_attr "type" "tst_l")])
 ;; On an address reg, cmpw may replace cmpl.
 (define_insn "*tstsi_internal"
   [(set (cc0)
-       (match_operand:SI 0 "nonimmediate_operand" "dm,r"))]
+       (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r")
+                (const_int 0)))]
   "!(TARGET_68020 || TARGET_COLDFIRE)"
   "@
    tst%.l %0
 
 ;; This can't use an address register, because comparisons
 ;; with address registers as second operand always test the whole word.
-(define_expand "tsthi"
-  [(set (cc0)
-       (match_operand:HI 0 "nonimmediate_operand" ""))]
-  ""
-  "m68k_last_compare_had_fp_operands = 0;")
-
 (define_insn "*tsthi_internal"
   [(set (cc0)
-       (match_operand:HI 0 "nonimmediate_operand" "dm"))]
+       (compare (match_operand:HI 0 "nonimmediate_operand" "dm")
+                (const_int 0)))]
   ""
   "tst%.w %0"
   [(set_attr "type" "tst")])
 
-(define_expand "tstqi"
-  [(set (cc0)
-       (match_operand:QI 0 "nonimmediate_operand" ""))]
-  ""
-  "m68k_last_compare_had_fp_operands = 0;")
-
 (define_insn "*tstqi_internal"
   [(set (cc0)
-       (match_operand:QI 0 "nonimmediate_operand" "dm"))]
+       (compare (match_operand:QI 0 "nonimmediate_operand" "dm")
+                (const_int 0)))]
   ""
   "tst%.b %0"
   [(set_attr "type" "tst")])
 
-(define_expand "tst<mode>"
-  [(set (cc0)
-       (match_operand:FP 0 "general_operand" ""))]
-  "TARGET_HARD_FLOAT"
-{
-  m68k_last_compare_had_fp_operands = 1;
-})
-
 (define_insn "tst<mode>_68881"
   [(set (cc0)
-       (match_operand:FP 0 "general_operand" "f<FP:dreg>m"))]
+       (compare (match_operand:FP 0 "general_operand" "f<FP:dreg>m")
+                (match_operand:FP 1 "const0_operand" "H")))]
   "TARGET_68881"
 {
   cc_status.flags = CC_IN_68881;
 
 (define_insn "tst<mode>_cf"
   [(set (cc0)
-       (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U"))]
+       (compare (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U")
+                (match_operand:FP 1 "const0_operand" "H")))]
   "TARGET_COLDFIRE_FPU"
 {
   cc_status.flags = CC_IN_68881;
 \f
 ;; compare instructions.
 
-(define_expand "cmpdi"
-  [(parallel
-    [(set (cc0)
-         (compare (match_operand:DI 0 "nonimmediate_operand" "")
-                  (match_operand:DI 1 "general_operand" "")))
-     (clobber (match_scratch:DI 2 ""))])]
-  ""
-  "m68k_last_compare_had_fp_operands = 0;")
-
-(define_insn ""
-  [(set (cc0)
-       (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
-                (match_operand:DI 2 "general_operand" "d,0")))
-   (clobber (match_scratch:DI 0 "=d,d"))]
+(define_insn "*cmpdi_internal"
+ [(set (cc0)
+       (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
+                (match_operand:DI 2 "general_operand" "d,0")))
+  (clobber (match_scratch:DI 0 "=d,d"))]
   ""
 {
   if (rtx_equal_p (operands[0], operands[1]))
     }
 })
 
-(define_expand "cmpsi"
-  [(set (cc0)
-       (compare (match_operand:SI 0 "nonimmediate_operand" "")
-                (match_operand:SI 1 "general_operand" "")))]
+(define_insn "cmpdi"
+ [(set (cc0)
+       (compare (match_operand:DI 0 "nonimmediate_operand")
+                (match_operand:DI 1 "general_operand")))
+  (clobber (match_scratch:DI 2))]
+  ""
+  "")
+
+
+(define_expand "cbranchdi4"
+  [(set (pc)
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                      [(match_operand:DI 1 "nonimmediate_operand")
+                       (match_operand:DI 2 "general_operand")])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
   ""
 {
-  m68k_last_compare_had_fp_operands = 0;
+  if (operands[2] == const0_rtx)
+    emit_insn (gen_tstdi (operands[1]));
+  else
+    emit_insn (gen_cmpdi (operands[1], operands[2]));
+  operands[1] = cc0_rtx;
+  operands[2] = const0_rtx;
+})
+
+(define_expand "cstoredi4"
+  [(set (match_operand:QI 0 "register_operand")
+       (match_operator:QI 1 "ordered_comparison_operator"
+        [(match_operand:DI 2 "nonimmediate_operand")
+         (match_operand:DI 3 "general_operand")]))]
+  ""
+{
+  if (operands[3] == const0_rtx)
+    emit_insn (gen_tstdi (operands[2]));
+  else
+    emit_insn (gen_cmpdi (operands[2], operands[3]));
+  operands[2] = cc0_rtx;
+  operands[3] = const0_rtx;
 })
 
+
+(define_expand "cbranchsi4"
+  [(set (cc0)
+       (compare (match_operand:SI 1 "nonimmediate_operand" "")
+                (match_operand:SI 2 "general_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
+  ""
+  "")
+
+(define_expand "cstoresi4"
+  [(set (cc0)
+       (compare (match_operand:SI 2 "nonimmediate_operand" "")
+                (match_operand:SI 3 "general_operand" "")))
+   (set (match_operand:QI 0 "register_operand")
+       (match_operator:QI 1 "ordered_comparison_operator"
+         [(cc0) (const_int 0)]))]
+  ""
+  "")
+
+
 ;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
 (define_insn ""
   [(set (cc0)
 }
   [(set_attr "type" "cmp_l")])
 
-(define_expand "cmphi"
+(define_expand "cbranchhi4"
   [(set (cc0)
-        (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
-                 (match_operand:HI 1 "general_src_operand" "")))]
-  "!TARGET_COLDFIRE"
-  "m68k_last_compare_had_fp_operands = 0;")
+       (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
+                (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
+  ""
+  "")
+
+(define_expand "cstorehi4"
+  [(set (cc0)
+       (compare (match_operand:HI 2 "nonimmediate_operand" "")
+                (match_operand:HI 3 "m68k_subword_comparison_operand" "")))
+   (set (match_operand:QI 0 "register_operand")
+       (match_operator:QI 1 "ordered_comparison_operator"
+         [(cc0) (const_int 0)]))]
+  ""
+  "")
 
 (define_insn ""
   [(set (cc0)
   return "cmp%.w %d1,%d0";
 })
 
-(define_expand "cmpqi"
+(define_expand "cbranchqi4"
   [(set (cc0)
-        (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
-                 (match_operand:QI 1 "general_src_operand" "")))]
-  "!TARGET_COLDFIRE"
-  "m68k_last_compare_had_fp_operands = 0;")
+       (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
+                (match_operand:QI 2 "m68k_subword_comparison_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
+  ""
+  "")
+
+(define_expand "cstoreqi4"
+  [(set (cc0)
+       (compare (match_operand:QI 2 "nonimmediate_src_operand" "")
+                (match_operand:QI 3 "m68k_subword_comparison_operand" "")))
+   (set (match_operand:QI 0 "register_operand")
+       (match_operator:QI 1 "ordered_comparison_operator"
+         [(cc0) (const_int 0)]))]
+  ""
+  "")
 
 (define_insn ""
   [(set (cc0)
   return "cmp%.b %d1,%d0";
 })
 
-(define_expand "cmp<mode>"
+(define_expand "cbranch<mode>4"
   [(set (cc0)
-       (compare (match_operand:FP 0 "register_operand" "")
-                (match_operand:FP 1 "fp_src_operand" "")))]
+       (compare (match_operand:FP 1 "register_operand" "")
+                (match_operand:FP 2 "fp_src_operand" "")))
+   (set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
   "TARGET_HARD_FLOAT"
-  "m68k_last_compare_had_fp_operands = 1;")
+  "")
+
+(define_expand "cstore<mode>4"
+  [(set (cc0)
+       (compare (match_operand:FP 2 "register_operand" "")
+                (match_operand:FP 3 "fp_src_operand" "")))
+   (set (match_operand:QI 0 "register_operand")
+       (match_operator:QI 1 "m68k_cstore_comparison_operator"
+         [(cc0) (const_int 0)]))]
+  "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)"
+  "if (TARGET_COLDFIRE && operands[2] != const0_rtx)
+     FAIL;")
 
 (define_insn "*cmp<mode>_68881"
   [(set (cc0)
 ;; from a MEM at a constant bit position if we can't use this as a constraint.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_src_operand" "oS")
-                           (const_int 1)
-                           (minus:SI (const_int 7)
-                                     (match_operand:SI 1 "general_operand" "di"))))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS")
+                              (const_int 1)
+                              (minus:SI (const_int 7)
+                                        (match_operand:SI 1 "general_operand" "di")))
+            (const_int 0)))]
   "!TARGET_COLDFIRE"
 {
   return output_btst (operands, operands[1], operands[0], insn, 7);
 ;; has been deleted.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
-                           (const_int 1)
-                           (minus:SI (const_int 7)
-                                     (match_operand:SI 1 "general_operand" "d"))))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+                              (const_int 1)
+                              (minus:SI (const_int 7)
+                                        (match_operand:SI 1 "general_operand" "d")))
+            (const_int 0)))]
   "TARGET_COLDFIRE"
 {
   return output_btst (operands, operands[1], operands[0], insn, 7);
 })
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
-                           (const_int 1)
-                           (minus:SI (const_int 31)
-                                     (match_operand:SI 1 "general_operand" "di"))))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+                              (const_int 1)
+                              (minus:SI (const_int 31)
+                                        (match_operand:SI 1 "general_operand" "di")))
+            (const_int 0)))]
   ""
 {
   return output_btst (operands, operands[1], operands[0], insn, 31);
 ;; are automatically masked to 3 or 5 bits.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
-                           (const_int 1)
-                           (minus:SI (const_int 7)
-                                     (and:SI
-                                      (match_operand:SI 1 "register_operand" "d")
-                                      (const_int 7)))))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+                              (const_int 1)
+                              (minus:SI (const_int 7)
+                                        (and:SI
+                                         (match_operand:SI 1 "register_operand" "d")
+                                         (const_int 7))))
+            (const_int 0)))]
   ""
 {
   return output_btst (operands, operands[1], operands[0], insn, 7);
 })
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
-                           (const_int 1)
-                           (minus:SI (const_int 31)
-                                     (and:SI
-                                      (match_operand:SI 1 "register_operand" "d")
-                                      (const_int 31)))))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+                              (const_int 1)
+                              (minus:SI (const_int 31)
+                                        (and:SI
+                                         (match_operand:SI 1 "register_operand" "d")
+                                         (const_int 31))))
+            (const_int 0)))]
   ""
 {
   return output_btst (operands, operands[1], operands[0], insn, 31);
 ;; Nonoffsettable mem refs are ok in this one pattern
 ;; since we don't try to adjust them.
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
-                           (const_int 1)
-                           (match_operand:SI 1 "const_int_operand" "n")))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
+                             (const_int 1)
+                             (match_operand:SI 1 "const_int_operand" "n"))
+            (const_int 0)))]
   "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE"
 {
   operands[1] = GEN_INT (7 - INTVAL (operands[1]));
 })
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do")
-                           (const_int 1)
-                           (match_operand:SI 1 "const_int_operand" "n")))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
+                             (const_int 1)
+                           (match_operand:SI 1 "const_int_operand" "n"))
+            (const_int 0)))]
   "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == MEM)
 ;; The 'o' has been replaced with 'Q'.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "dQ")
-                           (const_int 1)
-                           (match_operand:SI 1 "const_int_operand" "n")))]
+  [(set
+    (cc0)
+    (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ")
+                             (const_int 1)
+                             (match_operand:SI 1 "const_int_operand" "n"))
+            (const_int 0)))]
   "TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == MEM)
 {
   rtx tmp, base, offset;
 
-  if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
+  /* Recognize the case where operand[1] is a reference to thread-local
+     data and load its address to a register.  */
+  if (!TARGET_PCREL && m68k_tls_reference_p (operands[1], false))
+    {
+      rtx tmp = operands[1];
+      rtx addend = NULL;
+
+      if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+        {
+          addend = XEXP (XEXP (tmp, 0), 1);
+          tmp = XEXP (XEXP (tmp, 0), 0);
+        }
+
+      gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+      gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
+
+      tmp = m68k_legitimize_tls_address (tmp);
+
+      if (addend)
+        {
+         if (!REG_P (tmp))
+           {
+             rtx reg;
+
+             reg = gen_reg_rtx (Pmode);
+             emit_move_insn (reg, tmp);
+             tmp = reg;
+           }
+
+          tmp = gen_rtx_PLUS (SImode, tmp, addend);
+       }
+
+      operands[1] = tmp;
+    }
+  else if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
     {
       /* The source is an address which requires PIC relocation.
          Call legitimize_pic_address with the source, mode, and a relocation
 })
 
 (define_insn "extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-       (sign_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "rm")))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,o,o,<")
+       (sign_extend:DI
+        (match_operand:SI 1 "nonimmediate_src_operand" "rm,rm,r<Q>,rm")))
+   (clobber (match_scratch:SI 2 "=X,d,d,d"))]
   ""
 {
   CC_STATUS_INIT;
-  if (TARGET_68020 || TARGET_COLDFIRE)
-    return "move%.l %1,%R0\;smi %0\;extb%.l %0";
-  else
-    return "move%.l %1,%R0\;smi %0\;ext%.w %0\;ext%.l %0";
-})
 
-(define_insn "*extendsidi2_mem"
-  [(set (match_operand:DI 0 "memory_operand" "=o,<")
-       (sign_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "rm,rm")))
-   (clobber (match_scratch:SI 2 "=d,d"))]
-   ""
-{
-  CC_STATUS_INIT;
+  if (which_alternative == 0)
+    /* Handle alternative 0.  */
+    {
+      if (TARGET_68020 || TARGET_COLDFIRE)
+        return "move%.l %1,%R0\;smi %0\;extb%.l %0";
+      else
+        return "move%.l %1,%R0\;smi %0\;ext%.w %0\;ext%.l %0";
+    }
+
+  /* Handle alternatives 1, 2 and 3.  We don't need to adjust address by 4
+     in alternative 3 because autodecrement will do that for us.  */
   operands[3] = adjust_address (operands[0], SImode,
-                               which_alternative == 0 ? 4 : 0);
+                               which_alternative == 3 ? 0 : 4);
   operands[0] = adjust_address (operands[0], SImode, 0);
+
   if (TARGET_68020 || TARGET_COLDFIRE)
     return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
   else
     return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
-})
+}
+  [(set_attr "ok_for_coldfire" "yes,no,yes,yes")])
 
 ;; Special case when one can avoid register clobbering, copy and test
 ;; Maybe there is a way to make that the general case, by forcing the
   "* return output_addsi3 (operands);")
 
 (define_insn_and_split "*addsi3_5200"
-  [(set (match_operand:SI 0 "nonimmediate_operand"         "=mr,mr,a,m,r,  ?a, ?a,?a,?a")
-       (plus:SI (match_operand:SI 1 "general_operand"     "%0, 0, 0,0,0,   a,  a, r, a")
-                (match_operand:SI 2 "general_src_operand" " I, L, J,d,mrKi,Cj, r, a, J")))]
+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=mr,mr,a,  m,r,  ?a, ?a,?a,?a")
+       (plus:SI (match_operand:SI 1 "general_operand"     "%0, 0, 0,  0,0,   a,  a, r, a")
+                (match_operand:SI 2 "general_src_operand" " I, L, JCu,d,mrKi,Cj, r, a, JCu")))]
   "TARGET_COLDFIRE"
 {
   switch (which_alternative)
        (plus:SI (match_dup 0)
                 (match_dup 1)))]
   ""
-  [(set_attr "type" "aluq_l,aluq_l,lea,alu_l,alu_l,*,lea,lea,lea")
-   (set_attr "opy" "2,2,*,2,2,*,*,*,*")
-   (set_attr "opy_type" "*,*,mem5,*,*,*,mem6,mem6,mem5")])
+  [(set_attr "type"     "aluq_l,aluq_l,lea, alu_l,alu_l,*,lea, lea, lea")
+   (set_attr "opy"      "2,     2,     *,   2,    2,    *,*,   *,   *")
+   (set_attr "opy_type" "*,     *,     mem5,*,    *,    *,mem6,mem6,mem5")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
 
 (define_insn ""
   [(set (cc0)
-       (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
-                        (match_operand:SI 1 "const_int_operand" "n")
-                        (match_operand:SI 2 "general_operand" "dn")))]
+       (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+                                 (match_operand:SI 1 "const_int_operand" "n")
+                                 (match_operand:SI 2 "general_operand" "dn"))
+                (const_int 0)))]
   "TARGET_68020 && TARGET_BITFIELD"
 {
   if (operands[1] == const1_rtx
 ;;; now handle the register cases
 (define_insn ""
   [(set (cc0)
-       (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
-                        (match_operand:SI 1 "const_int_operand" "n")
-                        (match_operand:SI 2 "general_operand" "dn")))]
+       (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+                                 (match_operand:SI 1 "const_int_operand" "n")
+                                 (match_operand:SI 2 "general_operand" "dn"))
+                (const_int 0)))]
   "TARGET_68020 && TARGET_BITFIELD"
 {
   if (operands[1] == const1_rtx
 \f
 (define_insn "scc0_di"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
-    (match_operator 1 "valid_dbcc_comparison_p"
+    (match_operator 1 "ordered_comparison_operator"
       [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
   "! TARGET_COLDFIRE"
 {
 
 (define_insn "scc0_di_5200"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d")
-    (match_operator 1 "valid_dbcc_comparison_p"
+    (match_operator 1 "ordered_comparison_operator"
       [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
   "TARGET_COLDFIRE"
 {
 
 (define_insn "scc_di"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm")
-    (match_operator 1 "valid_dbcc_comparison_p"
+    (match_operator 1 "ordered_comparison_operator"
       [(match_operand:DI 2 "general_operand" "ro,r")
        (match_operand:DI 3 "general_operand" "r,ro")]))]
   "! TARGET_COLDFIRE"
 
 (define_insn "scc_di_5200"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d")
-    (match_operator 1 "valid_dbcc_comparison_p"
+    (match_operator 1 "ordered_comparison_operator"
       [(match_operand:DI 2 "general_operand" "ro,r")
        (match_operand:DI 3 "general_operand" "r,ro")]))]
   "TARGET_COLDFIRE"
 ;; memory, but we cannot allow it to be in memory in case the address
 ;; needs to be reloaded.
 
-(define_expand "seq"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (eq:QI (cc0) (const_int 0)))]
-  ""
-{
-  if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
-      && m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
-})
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (eq:QI (cc0) (const_int 0)))]
   OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0");
 })
 
-(define_expand "sne"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (ne:QI (cc0) (const_int 0)))]
-  ""
-{
-  if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
-      && m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
-})
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ne:QI (cc0) (const_int 0)))]
   OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0");
 })
 
-(define_expand "sgt"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (gt:QI (cc0) (const_int 0)))]
-  ""
-{
-  if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
-      && m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
-})
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (gt:QI (cc0) (const_int 0)))]
   OUTPUT_JUMP ("sgt %0", "fsgt %0", 0);
 })
 
-(define_expand "sgtu"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (gtu:QI (cc0) (const_int 0)))]
-  ""
-  "")
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (gtu:QI (cc0) (const_int 0)))]
   return "shi %0";
 })
 
-(define_expand "slt"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (lt:QI (cc0) (const_int 0)))]
-  ""
-{
-  if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
-      && m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
-})
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (lt:QI (cc0) (const_int 0)))]
    OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0");
 })
 
-(define_expand "sltu"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (ltu:QI (cc0) (const_int 0)))]
-  ""
-  "")
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ltu:QI (cc0) (const_int 0)))]
    return "scs %0";
 })
 
-(define_expand "sge"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (ge:QI (cc0) (const_int 0)))]
-  ""
-{
-  if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
-      && m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
-})
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ge:QI (cc0) (const_int 0)))]
    OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0");
 })
 
-(define_expand "sgeu"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (geu:QI (cc0) (const_int 0)))]
-  ""
-  "")
-
 (define_insn "*scc"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (geu:QI (cc0) (const_int 0)))]
 }
   [(set_attr "type" "scc")])
 
-(define_expand "sle"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (le:QI (cc0) (const_int 0)))]
-  ""
-{
-  if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
-      && m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
-})
-
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=d")
        (le:QI (cc0) (const_int 0)))]
   OUTPUT_JUMP ("sle %0", "fsle %0", 0);
 })
 
-(define_expand "sleu"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (leu:QI (cc0) (const_int 0)))]
-  ""
-  "")
-
 (define_insn "*sls"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (leu:QI (cc0) (const_int 0)))]
 }
   [(set_attr "type" "scc")])
 
-(define_expand "sordered"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (ordered:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sordered_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ordered:QI (cc0) (const_int 0)))]
   return "fsor %0";
 })
 
-(define_expand "sunordered"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (unordered:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sunordered_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (unordered:QI (cc0) (const_int 0)))]
   return "fsun %0";
 })
 
-(define_expand "suneq"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (uneq:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*suneq_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (uneq:QI (cc0) (const_int 0)))]
   return "fsueq %0";
 })
 
-(define_expand "sunge"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (unge:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sunge_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (unge:QI (cc0) (const_int 0)))]
   return "fsuge %0";
 })
 
-(define_expand "sungt"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (ungt:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sungt_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ungt:QI (cc0) (const_int 0)))]
   return "fsugt %0";
 })
 
-(define_expand "sunle"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (unle:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sunle_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (unle:QI (cc0) (const_int 0)))]
   return "fsule %0";
 })
 
-(define_expand "sunlt"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (unlt:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sunlt_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (unlt:QI (cc0) (const_int 0)))]
   return "fsult %0";
 })
 
-(define_expand "sltgt"
-  [(set (match_operand:QI 0 "register_operand" "")
-       (ltgt:QI (cc0) (const_int 0)))]
-  "TARGET_68881 && !TUNE_68060"
-{
-  gcc_assert (m68k_last_compare_had_fp_operands);
-  m68k_last_compare_had_fp_operands = 0;
-})
-
 (define_insn "*sltgt_1"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ltgt:QI (cc0) (const_int 0)))]
   "trap #7"
   [(set_attr "type" "trap")])
 
-(define_expand "conditional_trap"
-  [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
+(define_expand "ctrapdi4"
+  [(trap_if (match_operator 0 "ordered_comparison_operator"
                            [(cc0) (const_int 0)])
-           (match_operand:SI 1 "const_int_operand" "I"))]
+           (match_operand:SI 3 "const1_operand" ""))]
   "TARGET_68020"
 {
-  if (m68k_last_compare_had_fp_operands)
-    {
-      m68k_last_compare_had_fp_operands = 0;
-      FAIL;
-    }
+  if (operands[2] == const0_rtx)
+    emit_insn (gen_tstdi (operands[1]));
+  else
+    emit_insn (gen_cmpdi (operands[1], operands[2]));
+  operands[1] = cc0_rtx;
+  operands[2] = const0_rtx;
 })
 
+(define_expand "ctrapsi4"
+  [(set (cc0)
+       (compare (match_operand:SI 1 "nonimmediate_operand" "")
+                (match_operand:SI 2 "general_operand" "")))
+   (trap_if (match_operator 0 "ordered_comparison_operator"
+                           [(cc0) (const_int 0)])
+           (match_operand:SI 3 "const1_operand" ""))]
+  "TARGET_68020"
+  "")
+
+(define_expand "ctraphi4"
+  [(set (cc0)
+       (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
+                (match_operand:HI 2 "general_src_operand" "")))
+   (trap_if (match_operator 0 "ordered_comparison_operator"
+                           [(cc0) (const_int 0)])
+           (match_operand:SI 3 "const1_operand" ""))]
+  "TARGET_68020"
+  "")
+
+(define_expand "ctrapqi4"
+  [(set (cc0)
+       (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
+                (match_operand:QI 2 "general_src_operand" "")))
+   (trap_if (match_operator 0 "ordered_comparison_operator"
+                           [(cc0) (const_int 0)])
+           (match_operand:SI 3 "const1_operand" ""))]
+  "TARGET_68020"
+  "")
+
 (define_insn "*conditional_trap"
-  [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
+  [(trap_if (match_operator 0 "ordered_comparison_operator"
                            [(cc0) (const_int 0)])
-           (match_operand:SI 1 "const_int_operand" "I"))]
+           (match_operand:SI 1 "const1_operand" "I"))]
   "TARGET_68020 && ! flags_in_68881 ()"
 {
   switch (GET_CODE (operands[0]))