diff gcc/config/m68k/m68k.md @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents 77e2b8dfacca
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/config/m68k/m68k.md	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/config/m68k/m68k.md	Fri Oct 27 22:46:09 2017 +0900
@@ -1,7 +1,5 @@
 ;;- 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, 2008, 2009
-;;  Free Software Foundation, Inc.
+;;  Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
 ;; This file is part of GCC.
 
@@ -124,6 +122,10 @@
 
 (define_constants
   [(UNSPECV_BLOCKAGE	0)
+   (UNSPECV_CAS_1	1)
+   (UNSPECV_CAS_2	2)
+   (UNSPECV_TAS_1	3)
+   (UNSPECV_TAS_2	4)
   ])
 
 ;; Registers by name.
@@ -250,11 +252,15 @@
 
 ;; Define 'enabled' attribute.
 (define_attr "enabled" ""
-  (cond [(and (ne (symbol_ref "TARGET_COLDFIRE") (const_int 0))
+  (cond [(and (match_test "TARGET_COLDFIRE")
 	      (eq_attr "ok_for_coldfire" "no"))
 	 (const_int 0)]
  	(const_int 1)))
 
+;; Mode macros for integer operations.
+(define_mode_iterator I [QI HI SI])
+(define_mode_attr sz [(QI "%.b") (HI "%.w") (SI "%.l")])
+
 ;; Mode macros for floating point operations.
 ;; Valid floating point modes
 (define_mode_iterator FP [SF DF (XF "TARGET_68881")])
@@ -483,10 +489,19 @@
 
 
 ;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
+;;
+;; In theory we ought to be able to use some 'S' constraints and
+;; operand predicates that allow PC-rel addressing modes in the
+;; comparison patterns and expanders below.   But we would have to be
+;; cognizant of the fact that PC-rel addresses are not allowed for
+;; both operands and determining whether or not we emit the operands in
+;; order or reversed is not trivial to do just based on the constraints
+;; and operand predicates.  So to be safe, just don't allow the PC-rel
+;; versions in the various comparison expanders, patterns, for comparisons.
 (define_insn ""
   [(set (cc0)
-        (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mSr,mSa,>")
-                 (match_operand:SI 1 "general_src_operand" "mSr,mSa,KTr,Ksr,>")))]
+        (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>")
+                 (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))]
   "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
@@ -523,7 +538,7 @@
 
 (define_expand "cbranchhi4"
   [(set (cc0)
-	(compare (match_operand:HI 1 "nonimmediate_src_operand" "")
+	(compare (match_operand:HI 1 "nonimmediate_operand" "")
 		 (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
    (set (pc)
 	(if_then_else (match_operator 0 "ordered_comparison_operator"
@@ -545,8 +560,8 @@
 
 (define_insn ""
   [(set (cc0)
-        (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>")
-                 (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))]
+        (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
+                 (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
   "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
@@ -562,7 +577,7 @@
 
 (define_expand "cbranchqi4"
   [(set (cc0)
-	(compare (match_operand:QI 1 "nonimmediate_src_operand" "")
+	(compare (match_operand:QI 1 "nonimmediate_operand" "")
 		 (match_operand:QI 2 "m68k_subword_comparison_operand" "")))
    (set (pc)
 	(if_then_else (match_operator 0 "ordered_comparison_operator"
@@ -574,7 +589,7 @@
 
 (define_expand "cstoreqi4"
   [(set (cc0)
-	(compare (match_operand:QI 2 "nonimmediate_src_operand" "")
+	(compare (match_operand:QI 2 "nonimmediate_operand" "")
 		 (match_operand:QI 3 "m68k_subword_comparison_operand" "")))
    (set (match_operand:QI 0 "register_operand")
 	(match_operator:QI 1 "ordered_comparison_operator"
@@ -584,8 +599,8 @@
 
 (define_insn ""
   [(set (cc0)
-        (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>")
-                 (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))]
+        (compare (match_operand:QI 0 "nonimmediate_operand" "dn,dm,>")
+                 (match_operand:QI 1 "general_operand" "dm,nd,>")))]
   "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
@@ -691,7 +706,7 @@
 			       (minus:SI (const_int 31)
 				         (match_operand:SI 1 "general_operand" "di")))
 	     (const_int 0)))]
-  ""
+  "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
 {
   return output_btst (operands, operands[1], operands[0], insn, 31);
 })
@@ -750,9 +765,10 @@
     (cc0)
     (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
 			      (const_int 1)
-			    (match_operand:SI 1 "const_int_operand" "n"))
+			      (match_operand:SI 1 "const_int_operand" "n"))
 	     (const_int 0)))]
-  "!TARGET_COLDFIRE"
+  "!TARGET_COLDFIRE
+   && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
 {
   if (GET_CODE (operands[0]) == MEM)
     {
@@ -775,7 +791,8 @@
 			      (const_int 1)
 			      (match_operand:SI 1 "const_int_operand" "n"))
 	     (const_int 0)))]
-  "TARGET_COLDFIRE"
+  "TARGET_COLDFIRE
+   && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
 {
   if (GET_CODE (operands[0]) == MEM)
     {
@@ -1119,7 +1136,7 @@
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves. */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 })
 
@@ -1133,7 +1150,7 @@
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves. */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 })
 
@@ -1203,10 +1220,8 @@
 {
   if (which_alternative == 4 || which_alternative == 5) {
     rtx xoperands[2];
-    REAL_VALUE_TYPE r;
     long l;
-    REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+    REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), l);
     xoperands[0] = operands[0];
     xoperands[1] = GEN_INT (l);
     if (which_alternative == 5) {
@@ -1262,7 +1277,7 @@
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves. */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 })
 
@@ -1276,7 +1291,7 @@
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves. */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 })
 
@@ -1345,7 +1360,6 @@
   "TARGET_COLDFIRE_FPU"
 {
   rtx xoperands[3];
-  REAL_VALUE_TYPE r;
   long l[2];
 
   switch (which_alternative)
@@ -1361,8 +1375,7 @@
     case 4: case 5: case 6:
       return output_move_double (operands);
     case 7:
-      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-      REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+      REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), l);
       xoperands[0] = operands[0];
       xoperands[1] = GEN_INT (l[0]);
       xoperands[2] = GEN_INT (l[1]);
@@ -1383,7 +1396,7 @@
 ;; ??? The XFmode patterns are schizophrenic about whether constants are
 ;; allowed.  Most but not all have predicates and constraint that disallow
 ;; constants.  Most but not all have output templates that handle constants.
-;; See also LEGITIMATE_CONSTANT_P.
+;; See also TARGET_LEGITIMATE_CONSTANT_P.
 
 (define_expand "movxf"
   [(set (match_operand:XF 0 "nonimmediate_operand" "")
@@ -1566,7 +1579,7 @@
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
 	(truncate:QI
 	 (match_operand:SI 1 "general_src_operand" "doJS,i")))]
-  ""
+  "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == REG)
     {
@@ -1584,7 +1597,7 @@
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
 	(truncate:QI
 	 (match_operand:HI 1 "general_src_operand" "doJS,i")))]
-  ""
+  "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == REG
       && (GET_CODE (operands[1]) == MEM
@@ -1611,7 +1624,7 @@
   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm,d")
 	(truncate:HI
 	 (match_operand:SI 1 "general_src_operand" "roJS,i")))]
-  ""
+  "!TARGET_COLDFIRE"
 {
   if (GET_CODE (operands[0]) == REG)
     {
@@ -1862,9 +1875,11 @@
 ;; Maybe there is a way to make that the general case, by forcing the
 ;; result of the SI tree to be in the lower register of the DI target
 
+;; Don't allow memory for operand 1 as that would require an earlyclobber
+;; which results in worse code
 (define_insn "extendplussidi"
   [(set (match_operand:DI 0 "register_operand" "=d")
-    (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rmn")
+    (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rn")
             (match_operand:SI 2 "general_operand" "rmn"))))]
   ""
 {
@@ -2401,7 +2416,8 @@
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
 	{
 	  operands[1] = gen_rtx_MEM (SImode,
-				     plus_constant (XEXP(operands[0], 0), -8));
+				     plus_constant (Pmode,
+						    XEXP(operands[0], 0), -8));
 	  return "move%.l %0,%3\;add%.l %R2,%0\;addx%.l %2,%3\;move%.l %3,%1";
 	}
       else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
@@ -2899,7 +2915,8 @@
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
 	{
 	  operands[1]
-	    = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[0], 0), -8));
+	    = gen_rtx_MEM (SImode, plus_constant (Pmode,
+						  XEXP (operands[0], 0), -8));
 	  return "move%.l %0,%3\;sub%.l %R2,%0\;subx%.l %2,%3\;move%.l %3,%1";
 	}
       else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
@@ -3587,72 +3604,6 @@
 
 ;; logical-and instructions
 
-;; "anddi3" is mainly here to help combine().
-(define_insn "anddi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d")
-	(and:DI (match_operand:DI 1 "general_operand" "%0,0")
-		(match_operand:DI 2 "general_operand" "dn,don")))]
-  "!TARGET_COLDFIRE"
-{
-  CC_STATUS_INIT;
-  /* We can get CONST_DOUBLE, but also const1_rtx etc.  */
-  if (CONSTANT_P (operands[2]))
-    {
-      rtx hi, lo;
-
-      split_double (operands[2], &hi, &lo);
-
-      switch (INTVAL (hi))
-	{
-	  case 0 :
-	    output_asm_insn ("clr%.l %0", operands);
-	    break;
-	  case -1 :
-	    break;
-	  default :
-	    {
-	    rtx xoperands[3];
-
-	    xoperands[0] = operands[0];
-	    xoperands[2] = hi;
-	    output_asm_insn (output_andsi3 (xoperands), xoperands);
-	    }
-	}
-      if (GET_CODE (operands[0]) == REG)
-	operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-      else
-	operands[0] = adjust_address (operands[0], SImode, 4);
-      switch (INTVAL (lo))
-	{
-	  case 0 :
-	    output_asm_insn ("clr%.l %0", operands);
-	    break;
-	  case -1 :
-	    break;
-	  default :
-	    {
-	    rtx xoperands[3];
-
-	    xoperands[0] = operands[0];
-	    xoperands[2] = lo;
-	    output_asm_insn (output_andsi3 (xoperands), xoperands);
-	    }
-	}
-      return "";
-    }
-  if (GET_CODE (operands[0]) != REG)
-    {
-      operands[1] = adjust_address (operands[0], SImode, 4);
-      return "and%.l %2,%0\;and%.l %R2,%1";
-    }
-  if (GET_CODE (operands[2]) != REG)
-    {
-      operands[1] = adjust_address (operands[2], SImode, 4);
-      return "and%.l %2,%0\;and%.l %1,%R0";
-    }
-  return "and%.l %2,%0\;and%.l %R2,%R0";
-})
-
 ;; Prevent AND from being made with sp.  This doesn't exist in the machine
 ;; and reload will cause inefficient code.  Since sp is a FIXED_REG, we
 ;; can't allocate pseudos into it.
@@ -3770,76 +3721,6 @@
     return "or%.w %1,%0";
 })
 
-;; "iordi3" is mainly here to help combine().
-(define_insn "iordi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d")
-	(ior:DI (match_operand:DI 1 "general_operand" "%0,0")
-		(match_operand:DI 2 "general_operand" "dn,don")))]
-  "!TARGET_COLDFIRE"
-{
-  CC_STATUS_INIT;
-  /* We can get CONST_DOUBLE, but also const1_rtx etc.  */
-  if (CONSTANT_P (operands[2]))
-    {
-      rtx hi, lo;
-
-      split_double (operands[2], &hi, &lo);
-
-      switch (INTVAL (hi))
-	{
-	  case 0 :
-	    break;
-	  case -1 :
-	    /* FIXME : a scratch register would be welcome here if operand[0]
-	       is not a register */
-	    output_asm_insn ("move%.l #-1,%0", operands);
-	    break;
-	  default :
-	    {
-	    rtx xoperands[3];
-
-	    xoperands[0] = operands[0];
-	    xoperands[2] = hi;
-	    output_asm_insn (output_iorsi3 (xoperands), xoperands);
-	    }
-	}
-      if (GET_CODE (operands[0]) == REG)
-	operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-      else
-	operands[0] = adjust_address (operands[0], SImode, 4);
-      switch (INTVAL (lo))
-	{
-	  case 0 :
-	    break;
-	  case -1 :
-	    /* FIXME : a scratch register would be welcome here if operand[0]
-	       is not a register */
-	    output_asm_insn ("move%.l #-1,%0", operands);
-	    break;
-	  default :
-	    {
-	    rtx xoperands[3];
-
-	    xoperands[0] = operands[0];
-	    xoperands[2] = lo;
-	    output_asm_insn (output_iorsi3 (xoperands), xoperands);
-	    }
-	}
-      return "";
-    }
-  if (GET_CODE (operands[0]) != REG)
-    {
-      operands[1] = adjust_address (operands[0], SImode, 4);
-      return "or%.l %2,%0\;or%.l %R2,%1";
-    }
-  if (GET_CODE (operands[2]) != REG)
-    {
-      operands[1] = adjust_address (operands[2], SImode, 4);
-      return "or%.l %2,%0\;or%.l %1,%R0";
-    }
-  return "or%.l %2,%0\;or%.l %R2,%R0";
-})
-
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
 	(ior:SI (match_operand:SI 1 "general_operand" "")
@@ -3947,79 +3828,6 @@
 
 ;; xor instructions
 
-;; "xordi3" is mainly here to help combine().
-(define_insn "xordi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=od")
-	(xor:DI (match_operand:DI 1 "general_operand" "%0")
-		(match_operand:DI 2 "general_operand" "dn")))]
-  "!TARGET_COLDFIRE"
-{
-  CC_STATUS_INIT;
-  /* We can get CONST_DOUBLE, but also const1_rtx etc.  */
-
-  if (CONSTANT_P (operands[2]))
-    {
-      rtx hi, lo;
-
-      split_double (operands[2], &hi, &lo);
-
-      switch (INTVAL (hi))
-	{
-	  case 0 :
-	    break;
-	  case -1 :
-	    output_asm_insn ("not%.l %0", operands);
-	    break;
-	  default :
-	    /* FIXME : a scratch register would be welcome here if
-	       -128 <= INTVAL (hi) < -1 */
-	    {
-	    rtx xoperands[3];
-
-	    xoperands[0] = operands[0];
-	    xoperands[2] = hi;
-	    output_asm_insn (output_xorsi3 (xoperands), xoperands);
-	    }
-	}
-      if (GET_CODE (operands[0]) == REG)
-	operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-      else
-	operands[0] = adjust_address (operands[0], SImode, 4);
-      switch (INTVAL (lo))
-	{
-	  case 0 :
-	    break;
-	  case -1 :
-	    output_asm_insn ("not%.l %0", operands);
-	    break;
-	  default :
-	    /* FIXME : a scratch register would be welcome here if
-	       -128 <= INTVAL (lo) < -1 */
-	    operands[2] = lo;
-	    /* FIXME : this should be merged with xorsi3 */
-	    {
-	    rtx xoperands[3];
-
-	    xoperands[0] = operands[0];
-	    xoperands[2] = lo;
-	    output_asm_insn (output_xorsi3 (xoperands), xoperands);
-	    }
-	}
-      return "";
-    }
-  if (GET_CODE (operands[0]) != REG)
-    {
-      operands[1] = adjust_address (operands[0], SImode, 4);
-      return "eor%.l %2,%0\;eor%.l %R2,%1";
-    }
-  if (GET_CODE (operands[2]) != REG)
-    {
-      operands[1] = adjust_address (operands[2], SImode, 4);
-      return "eor%.l %2,%0\;eor%.l %1,%R0";
-    }
-  return "eor%.l %2,%0\;eor%.l %R2,%R0";
-})
-
 (define_expand "xorsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
 	(xor:SI (match_operand:SI 1 "general_operand" "")
@@ -4028,9 +3836,9 @@
   "")
 
 (define_insn "xorsi3_internal"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=do,m")
-	(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
-                (match_operand:SI 2 "general_operand" "di,dKT")))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,o,m")
+	(xor:SI (match_operand:SI 1 "general_operand" "%0, 0,0")
+                (match_operand:SI 2 "general_operand" "di,dK,dKT")))]
 
   "!TARGET_COLDFIRE"
 {
@@ -4457,33 +4265,37 @@
 
 ;; bit indexing instructions
 
+(define_expand "clzsi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (clz:SI (match_operand:SI 1 "general_operand" "")))]
+  "ISA_HAS_FF1 || (TARGET_68020 && TARGET_BITFIELD)"
+{
+  if (ISA_HAS_FF1)
+    operands[1] = force_reg (SImode, operands[1]);
+})
+
+(define_insn "*clzsi2_68k"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (clz:SI (match_operand:SI 1 "general_operand" "do")))]
+  "TARGET_68020 && TARGET_BITFIELD"
+{
+  CC_STATUS_INIT;
+  return "bfffo %1{#0:#0},%0";
+})
+
 ;; ColdFire ff1 instruction implements clz.
-(define_insn "clzsi2"
+(define_insn "*clzsi2_cf"
   [(set (match_operand:SI 0 "register_operand" "=d")
  	(clz:SI (match_operand:SI 1 "register_operand" "0")))]
   "ISA_HAS_FF1"
-  "ff1 %0"
+{
+  CC_STATUS_INIT;
+  return "ff1 %0";
+}
   [(set_attr "type" "ext")])
 
 ;; one complement instructions
 
-;; "one_cmpldi2" is mainly here to help combine().
-(define_insn "one_cmpldi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=dm")
-	(not:DI (match_operand:DI 1 "general_operand" "0")))]
-  "!TARGET_COLDFIRE"
-{
-  CC_STATUS_INIT;
-  if (GET_CODE (operands[0]) == REG)
-    operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC
-        || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    operands[1] = operands[0];
-  else
-    operands[1] = adjust_address (operands[0], SImode, 4);
-  return "not%.l %1\;not%.l %0";
-})
-
 (define_expand "one_cmplsi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
 	(not:SI (match_operand:SI 1 "general_operand" "")))]
@@ -4535,25 +4347,18 @@
 
 ;; arithmetic shift instructions
 ;; We don't need the shift memory by 1 bit instruction
-
-(define_insn "ashldi_extsi"
+(define_insn_and_split "ashldi_extsi"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
     (ashift:DI
       (match_operator:DI 2 "extend_operator"
         [(match_operand:SI 1 "general_operand" "rm")])
       (const_int 32)))]
   ""
-{
-  CC_STATUS_INIT;
-  if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  else
-    operands[2] = adjust_address (operands[0], SImode, 4);
-  if (ADDRESS_REG_P (operands[0]))
-    return "move%.l %1,%0\;sub%.l %2,%2";
-  else
-    return "move%.l %1,%0\;clr%.l %2";
-})
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 2) (const_int 0))]
+  "split_di(operands, 1, operands + 2, operands + 3);")
 
 (define_insn "ashldi_sexthi"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,a*d")
@@ -4741,7 +4546,7 @@
 (define_expand "ashldi3"
   [(set (match_operand:DI 0 "register_operand" "")
 	(ashift:DI (match_operand:DI 1 "register_operand" "")
-		   (match_operand 2 "const_int_operand" "")))]
+		   (match_operand:SI 2 "const_int_operand" "")))]
   "!TARGET_COLDFIRE"
 {
   /* ???  This is a named pattern like this is not allowed to FAIL based
@@ -5010,7 +4815,7 @@
 (define_expand "ashrdi3"
   [(set (match_operand:DI 0 "register_operand" "")
 	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
-		     (match_operand 2 "const_int_operand" "")))]
+		     (match_operand:SI 2 "const_int_operand" "")))]
   "!TARGET_COLDFIRE"
 {
   /* ???  This is a named pattern like this is not allowed to FAIL based
@@ -5279,7 +5084,7 @@
 (define_expand "lshrdi3"
   [(set (match_operand:DI 0 "register_operand" "")
 	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
-		     (match_operand 2 "const_int_operand" "")))]
+		     (match_operand:SI 2 "const_int_operand" "")))]
   "!TARGET_COLDFIRE"
 {
   /* ???  This is a named pattern like this is not allowed to FAIL based
@@ -5408,19 +5213,19 @@
     return "rol%.w %2,%0";
 })
 
-(define_insn ""
+(define_insn "*rotlhi3_lowpart"
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
 	(rotate:HI (match_dup 0)
 		   (match_operand:HI 1 "general_operand" "dIP")))]
   "!TARGET_COLDFIRE"
 {
-  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+  if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) >= 8)
     {
-      operands[2] = GEN_INT (16 - INTVAL (operands[2]));
-      return "ror%.w %2,%0";
+      operands[1] = GEN_INT (16 - INTVAL (operands[1]));
+      return "ror%.w %1,%0";
     }
   else
-    return "rol%.w %2,%0";
+    return "rol%.w %1,%0";
 })
 
 (define_insn "rotlqi3"
@@ -5438,19 +5243,19 @@
     return "rol%.b %2,%0";
 })
 
-(define_insn ""
+(define_insn "*rotlqi3_lowpart"
   [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
 	(rotate:QI (match_dup 0)
 		   (match_operand:QI 1 "general_operand" "dI")))]
   "!TARGET_COLDFIRE"
 {
-  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+  if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) >= 4)
     {
-      operands[2] = GEN_INT (8 - INTVAL (operands[2]));
-      return "ror%.b %2,%0";
+      operands[1] = GEN_INT (8 - INTVAL (operands[1]));
+      return "ror%.b %1,%0";
     }
   else
-    return "rol%.b %2,%0";
+    return "rol%.b %1,%0";
 })
 
 (define_insn "rotrsi3"
@@ -5467,7 +5272,7 @@
   "!TARGET_COLDFIRE"
   "ror%.w %2,%0")
 
-(define_insn ""
+(define_insn "rotrhi_lowpart"
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
 	(rotatert:HI (match_dup 0)
 		     (match_operand:HI 1 "general_operand" "dI")))]
@@ -5487,6 +5292,19 @@
 		     (match_operand:QI 1 "general_operand" "dI")))]
   "!TARGET_COLDFIRE"
   "ror%.b %1,%0")
+
+(define_expand "bswapsi2"
+  [(set (match_operand:SI 0 "register_operand")
+	(bswap:SI (match_operand:SI 1 "register_operand")))]
+  "!TARGET_COLDFIRE"
+{
+  rtx x = operands[0];
+  emit_move_insn (x, operands[1]);
+  emit_insn (gen_rotrhi_lowpart (gen_lowpart (HImode, x), GEN_INT (8)));
+  emit_insn (gen_rotlsi3 (x, x, GEN_INT (16)));
+  emit_insn (gen_rotrhi_lowpart (gen_lowpart (HImode, x), GEN_INT (8)));
+  DONE;
+})
 
 
 ;; Bit set/clear in memory byte.
@@ -5518,6 +5336,45 @@
 }
   [(set_attr "type" "bitrw")])
 
+(define_insn "*bsetdreg"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+	(ior:SI (ashift:SI (const_int 1)
+			   (and:SI (match_operand:SI 1 "register_operand" "d")
+				   (const_int 31)))
+		(match_operand:SI 2 "register_operand" "0")))]
+  ""
+{
+  CC_STATUS_INIT;
+  return "bset %1,%0";
+}
+  [(set_attr "type" "bitrw")])
+
+(define_insn "*bchgdreg"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+	(xor:SI (ashift:SI (const_int 1)
+			   (and:SI (match_operand:SI 1 "register_operand" "d")
+				   (const_int 31)))
+		(match_operand:SI 2 "register_operand" "0")))]
+  ""
+{
+  CC_STATUS_INIT;
+  return "bchg %1,%0";
+}
+  [(set_attr "type" "bitrw")])
+
+(define_insn "*bclrdreg"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+	(and:SI (rotate:SI (const_int -2)
+			   (and:SI (match_operand:SI 1 "register_operand" "d")
+				   (const_int 31)))
+		(match_operand:SI 2 "register_operand" "0")))]
+  ""
+{
+  CC_STATUS_INIT;
+  return "bclr %1,%0";
+}
+  [(set_attr "type" "bitrw")])
+
 ;; clear bit, bit number is int
 (define_insn "bclrmemqi"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
@@ -5559,14 +5416,15 @@
 ; The move is allowed to be odd byte aligned, because that's still faster
 ; than an odd byte aligned bit-field instruction.
 ;
-(define_insn ""
+(define_insn "*insv_32_mem"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
 			 (const_int 32)
 			 (match_operand:SI 1 "const_int_operand" "n"))
 	(match_operand:SI 2 "general_src_operand" "rmSi"))]
   "TARGET_68020 && TARGET_BITFIELD
    && (INTVAL (operands[1]) % 8) == 0
-   && ! mode_dependent_address_p (XEXP (operands[0], 0))"
+   && ! mode_dependent_address_p (XEXP (operands[0], 0),
+                                  MEM_ADDR_SPACE (operands[0]))"
 {
   operands[0]
     = adjust_address (operands[0], SImode, INTVAL (operands[1]) / 8);
@@ -5574,31 +5432,18 @@
   return "move%.l %2,%0";
 })
 
-(define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+do")
+(define_insn "*insv_8_16_reg"
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
 			 (match_operand:SI 1 "const_int_operand" "n")
 			 (match_operand:SI 2 "const_int_operand" "n"))
 	(match_operand:SI 3 "register_operand" "d"))]
   "TARGET_68020 && TARGET_BITFIELD
+   && IN_RANGE (INTVAL (operands[2]), 0, 31)
    && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
-   && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
-   && (GET_CODE (operands[0]) == REG
-       || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
-{
-  if (REG_P (operands[0]))
-    {
-      if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
-        return "bfins %3,%0{%b2:%b1}";
-    }
-  else
-    operands[0] = adjust_address (operands[0],
-				  INTVAL (operands[1]) == 8 ? QImode : HImode,
-				  INTVAL (operands[2]) / 8);
-
-  if (GET_CODE (operands[3]) == MEM)
-    operands[3] = adjust_address (operands[3],
-				  INTVAL (operands[1]) == 8 ? QImode : HImode,
-				  (32 - INTVAL (operands[1])) / 8);
+   && INTVAL (operands[2]) % INTVAL (operands[1]) == 0"
+{
+  if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
+    return "bfins %3,%0{%b2:%b1}";
 
   if (INTVAL (operands[1]) == 8)
     return "move%.b %3,%0";
@@ -5613,14 +5458,15 @@
 ; The move is allowed to be odd byte aligned, because that's still faster
 ; than an odd byte aligned bit-field instruction.
 ;
-(define_insn ""
+(define_insn "*extzv_32_mem"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
 	(zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
 			 (const_int 32)
 			 (match_operand:SI 2 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
    && (INTVAL (operands[2]) % 8) == 0
-   && ! mode_dependent_address_p (XEXP (operands[1], 0))"
+   && ! mode_dependent_address_p (XEXP (operands[1], 0),
+                                  MEM_ADDR_SPACE (operands[1]))"
 {
   operands[1]
     = adjust_address (operands[1], SImode, INTVAL (operands[2]) / 8);
@@ -5628,33 +5474,21 @@
   return "move%.l %1,%0";
 })
 
-(define_insn ""
+(define_insn "*extzv_8_16_reg"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=&d")
-	(zero_extract:SI (match_operand:SI 1 "register_operand" "do")
+	(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
 			 (match_operand:SI 2 "const_int_operand" "n")
 			 (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
+   && IN_RANGE (INTVAL (operands[3]), 0, 31)
    && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
-   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
-   && (GET_CODE (operands[1]) == REG
-       || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
 {
   cc_status.flags |= CC_NOT_NEGATIVE;
-  if (REG_P (operands[1]))
-    {
-      if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
-	return "bfextu %1{%b3:%b2},%0";
-    }
-  else
-    operands[1]
-      = adjust_address (operands[1], SImode, INTVAL (operands[3]) / 8);
+  if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+    return "bfextu %1{%b3:%b2},%0";
 
   output_asm_insn ("clr%.l %0", operands);
-  if (GET_CODE (operands[0]) == MEM)
-    operands[0] = adjust_address (operands[0],
-				  INTVAL (operands[2]) == 8 ? QImode : HImode,
-				  (32 - INTVAL (operands[1])) / 8);
-
   if (INTVAL (operands[2]) == 8)
     return "move%.b %1,%0";
   return "move%.w %1,%0";
@@ -5667,14 +5501,15 @@
 ; The move is allowed to be odd byte aligned, because that's still faster
 ; than an odd byte aligned bit-field instruction.
 ;
-(define_insn ""
+(define_insn "*extv_32_mem"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
 	(sign_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
 			 (const_int 32)
 			 (match_operand:SI 2 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
    && (INTVAL (operands[2]) % 8) == 0
-   && ! mode_dependent_address_p (XEXP (operands[1], 0))"
+   && ! mode_dependent_address_p (XEXP (operands[1], 0),
+                                  MEM_ADDR_SPACE (operands[1]))"
 {
   operands[1]
     = adjust_address (operands[1], SImode, INTVAL (operands[2]) / 8);
@@ -5682,27 +5517,18 @@
   return "move%.l %1,%0";
 })
 
-(define_insn ""
+(define_insn "*extv_8_16_reg"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
-	(sign_extract:SI (match_operand:SI 1 "register_operand" "do")
+	(sign_extract:SI (match_operand:SI 1 "register_operand" "d")
 			 (match_operand:SI 2 "const_int_operand" "n")
 			 (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
+   && IN_RANGE (INTVAL (operands[3]), 0, 31)
    && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
-   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
-   && (GET_CODE (operands[1]) == REG
-       || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
-{
-  if (REG_P (operands[1]))
-    {
-      if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
-	return "bfexts %1{%b3:%b2},%0";
-    }
-  else
-    operands[1]
-      = adjust_address (operands[1],
-			INTVAL (operands[2]) == 8 ? QImode : HImode,
-			INTVAL (operands[3]) / 8);
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
+{
+  if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+    return "bfexts %1{%b3:%b2},%0";
 
   if (INTVAL (operands[2]) == 8)
     return "move%.b %1,%0\;extb%.l %0";
@@ -5721,7 +5547,7 @@
   "TARGET_68020 && TARGET_BITFIELD"
   "")
 
-(define_insn ""
+(define_insn "*extv_bfexts_mem"
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
 			 (match_operand:SI 2 "nonmemory_operand" "dn")
@@ -5737,7 +5563,7 @@
   "TARGET_68020 && TARGET_BITFIELD"
   "")
 
-(define_insn ""
+(define_insn "*extzv_bfextu_mem"
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
 			 (match_operand:SI 2 "nonmemory_operand" "dn")
@@ -5756,7 +5582,7 @@
   return "bfextu %1{%b3:%b2},%0";
 })
 
-(define_insn ""
+(define_insn "*insv_bfchg_mem"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
 			 (match_operand:SI 1 "nonmemory_operand" "dn")
 			 (match_operand:SI 2 "nonmemory_operand" "dn"))
@@ -5771,7 +5597,7 @@
   return "bfchg %0{%b2:%b1}";
 })
 
-(define_insn ""
+(define_insn "*insv_bfclr_mem"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
 			 (match_operand:SI 1 "nonmemory_operand" "dn")
 			 (match_operand:SI 2 "nonmemory_operand" "dn"))
@@ -5782,7 +5608,7 @@
   return "bfclr %0{%b2:%b1}";
 })
 
-(define_insn ""
+(define_insn "*insv_bfset_mem"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
 			 (match_operand:SI 1 "general_operand" "dn")
 			 (match_operand:SI 2 "general_operand" "dn"))
@@ -5797,11 +5623,22 @@
   [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "")
 			 (match_operand:SI 1 "const_int_operand" "")
 			 (match_operand:SI 2 "const_int_operand" ""))
-	(match_operand:SI 3 "register_operand" ""))]
+	(match_operand:SI 3 "reg_or_pow2_m1_operand" ""))]
   "TARGET_68020 && TARGET_BITFIELD"
-  "")
-
-(define_insn ""
+  "
+{
+  /* Special case initializing a field to all ones. */
+  if (GET_CODE (operands[3]) == CONST_INT)
+    {
+      if (exact_log2 (INTVAL (operands[3]) + 1) != INTVAL (operands[1]))
+	operands[3] = force_reg (SImode, operands[3]);
+      else
+	operands[3] = constm1_rtx;
+
+    }
+}")
+
+(define_insn "*insv_bfins_mem"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
 			 (match_operand:SI 1 "nonmemory_operand" "dn")
 			 (match_operand:SI 2 "nonmemory_operand" "dn"))
@@ -5812,20 +5649,20 @@
 ;; Now recognize bit-field insns that operate on registers
 ;; (or at least were intended to do so).
 
-(define_insn ""
+(define_insn "*extv_bfexts_reg"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(sign_extract:SI (match_operand:SI 1 "register_operand" "d")
 			 (match_operand:SI 2 "const_int_operand" "n")
 			 (match_operand:SI 3 "const_int_operand" "n")))]
-  "TARGET_68020 && TARGET_BITFIELD"
+  "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
   "bfexts %1{%b3:%b2},%0")
 
-(define_insn ""
+(define_insn "*extv_bfextu_reg"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
 			 (match_operand:SI 2 "const_int_operand" "n")
 			 (match_operand:SI 3 "const_int_operand" "n")))]
-  "TARGET_68020 && TARGET_BITFIELD"
+  "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
 {
   if (GET_CODE (operands[2]) == CONST_INT)
     {
@@ -5839,34 +5676,34 @@
   return "bfextu %1{%b3:%b2},%0";
 })
 
-(define_insn ""
+(define_insn "*insv_bfclr_reg"
   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
 			 (match_operand:SI 1 "const_int_operand" "n")
 			 (match_operand:SI 2 "const_int_operand" "n"))
 	(const_int 0))]
-  "TARGET_68020 && TARGET_BITFIELD"
+  "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
 {
   CC_STATUS_INIT;
   return "bfclr %0{%b2:%b1}";
 })
 
-(define_insn ""
+(define_insn "*insv_bfset_reg"
   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
 			 (match_operand:SI 1 "const_int_operand" "n")
 			 (match_operand:SI 2 "const_int_operand" "n"))
 	(const_int -1))]
-  "TARGET_68020 && TARGET_BITFIELD"
+  "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
 {
   CC_STATUS_INIT;
   return "bfset %0{%b2:%b1}";
 })
 
-(define_insn ""
+(define_insn "*insv_bfins_reg"
   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
 			 (match_operand:SI 1 "const_int_operand" "n")
 			 (match_operand:SI 2 "const_int_operand" "n"))
 	(match_operand:SI 3 "register_operand" "d"))]
-  "TARGET_68020 && TARGET_BITFIELD"
+  "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
 {
 #if 0
   /* These special cases are now recognized by a specific pattern.  */
@@ -5882,7 +5719,7 @@
 
 ;; Special patterns for optimizing bit-field instructions.
 
-(define_insn ""
+(define_insn "*tst_bftst_mem"
   [(set (cc0)
 	(compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
 				  (match_operand:SI 1 "const_int_operand" "n")
@@ -5908,13 +5745,14 @@
 
 
 ;;; now handle the register cases
-(define_insn ""
+(define_insn "*tst_bftst_reg"
   [(set (cc0)
 	(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"
+  "TARGET_68020 && TARGET_BITFIELD
+    && !(CONST_INT_P (operands[2]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
 {
   if (operands[1] == const1_rtx
       && GET_CODE (operands[2]) == CONST_INT)
@@ -6177,15 +6015,15 @@
 
 (define_insn "beq0_di"
   [(set (pc)
-    (if_then_else (eq (match_operand:DI 0 "general_operand" "d*ao,<>")
+    (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
             (const_int 0))
-        (label_ref (match_operand 1 "" ","))
+        (label_ref (match_operand 1 "" ",,"))
         (pc)))
-   (clobber (match_scratch:SI 2 "=d,d"))]
+   (clobber (match_scratch:SI 2 "=d,&d,d"))]
   ""
 {
   CC_STATUS_INIT;
-  if (which_alternative == 1)
+  if (which_alternative == 2)
     return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
   if ((cc_prev_status.value1
       && rtx_equal_p (cc_prev_status.value1, operands[0]))
@@ -6222,11 +6060,11 @@
 
 (define_insn "bne0_di"
   [(set (pc)
-    (if_then_else (ne (match_operand:DI 0 "general_operand" "do,*a")
+    (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
             (const_int 0))
-        (label_ref (match_operand 1 "" ","))
+        (label_ref (match_operand 1 "" ",,"))
         (pc)))
-   (clobber (match_scratch:SI 2 "=d,X"))]
+   (clobber (match_scratch:SI 2 "=d,&d,X"))]
   ""
 {
   if ((cc_prev_status.value1
@@ -6323,7 +6161,7 @@
 {
   OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
 }
-  [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))])
+  [(set_attr "type" "bcc")])
 
 (define_insn "bne"
   [(set (pc)
@@ -6335,7 +6173,7 @@
 {
   OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
 }
-  [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))])
+  [(set_attr "type" "bcc")])
 
 (define_insn "bgt"
   [(set (pc)
@@ -6353,7 +6191,7 @@
 
   OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
 }
-  [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))])
+  [(set_attr "type" "bcc")])
 
 (define_insn "bgtu"
   [(set (pc)
@@ -6389,7 +6227,7 @@
 
   OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0");
 }
-  [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))])
+  [(set_attr "type" "bcc")])
 
 (define_insn "bltu"
   [(set (pc)
@@ -6855,9 +6693,11 @@
 	      (use (label_ref (match_operand 1 "" "")))])]
   ""
 {
-#ifdef CASE_VECTOR_PC_RELATIVE
+#if CASE_VECTOR_PC_RELATIVE
     operands[0] = gen_rtx_PLUS (SImode, pc_rtx,
-				gen_rtx_SIGN_EXTEND (SImode, operands[0]));
+				TARGET_LONG_JUMP_TABLE_OFFSETS
+				? operands[0]
+				: gen_rtx_SIGN_EXTEND (SImode, operands[0]));
 #endif
 })
 
@@ -6872,12 +6712,26 @@
   [(set_attr "type" "jmp")])
 
 ;; Jump to variable address from dispatch table of relative addresses.
-(define_insn ""
+(define_insn "*tablejump_pcrel_si"
+  [(set (pc)
+	(plus:SI (pc)
+		 (match_operand:SI 0 "register_operand" "r")))
+   (use (label_ref (match_operand 1 "" "")))]
+  "TARGET_LONG_JUMP_TABLE_OFFSETS"
+{
+#ifdef ASM_RETURN_CASE_JUMP
+  ASM_RETURN_CASE_JUMP;
+#else
+  return MOTOROLA ? "jmp (2,pc,%0.l)" : "jmp pc@(2,%0:l)";
+#endif
+})
+
+(define_insn "*tablejump_pcrel_hi"
   [(set (pc)
 	(plus:SI (pc)
 		 (sign_extend:SI (match_operand:HI 0 "register_operand" "r"))))
    (use (label_ref (match_operand 1 "" "")))]
-  ""
+  "!TARGET_LONG_JUMP_TABLE_OFFSETS"
 {
 #ifdef ASM_RETURN_CASE_JUMP
   ASM_RETURN_CASE_JUMP;
@@ -7111,7 +6965,7 @@
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
@@ -7243,7 +7097,8 @@
 		      (match_operand:SI 1 "const_int_operand")))])]
   "TARGET_68020 || INTVAL (operands[1]) >= -0x8004"
 {
-  operands[2] = gen_frame_mem (SImode, plus_constant (stack_pointer_rtx, -4));
+  operands[2] = gen_frame_mem (SImode,
+			       plus_constant (Pmode, stack_pointer_rtx, -4));
 })
 
 (define_insn "*link"
@@ -7806,3 +7661,182 @@
   [(set_attr "type" "ib")])
 
 (include "cf.md")
+(include "sync.md")
+
+;; Convert
+;;
+;; 	move.l 4(%a0),%a0
+;; 	clr.b (%a0,%a1.l)
+;;
+;; into
+;;
+;; 	add.l 4(%a0),%a1
+;; 	clr.b (%a1)
+;;
+;; The latter is smaller.  It is faster on all models except m68060.
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
+			 (match_operand:SI 2 "const_int_operand" ""))))
+   (set (mem:QI (plus:SI (match_operand:SI 3 "register_operand" "")
+			 (match_operand:SI 4 "register_operand" "")))
+	(const_int 0))]
+  "(optimize_size || !TUNE_68060)
+   && (operands[0] == operands[3] || operands[0] == operands[4])
+   && ADDRESS_REG_P (operands[1])
+   && ADDRESS_REG_P ((operands[0] == operands[3]) ? operands[4] : operands[3])
+   && peep2_reg_dead_p (2, operands[3])
+   && peep2_reg_dead_p (2, operands[4])"
+  [(set (match_dup 5)
+	(plus:SI (match_dup 5)
+		 (mem:SI (plus:SI (match_dup 1)
+				  (match_dup 2)))))
+   (set (mem:QI (match_dup 5))
+	(const_int 0))]
+  "operands[5] = (operands[0] == operands[3]) ? operands[4] : operands[3];")
+
+;; We want to turn
+;;   moveq const,dX
+;;   cmp.l dX,dY
+;;   je/jne
+;;
+;; into
+;;   addq/subq -const,dY
+;;   cmp.l dY, 0
+;;   je/jne
+;;
+;; dX and dY must both be dead at the end of the sequence and the constant
+;; must be valid for addq/subq.
+;;
+;; Essentially we're making it trivial for final to realize the comparison
+;; is not needed
+;;
+;; Testing has shown a variant where the operands are reversed in the
+;; comparison never hits, so I have not included that variant.
+;;
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "addq_subq_operand" ""))
+   (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+		       (match_dup 0)))
+   (set (pc) (if_then_else (match_operator 5 "equality_comparison_operator"
+			    [(cc0) (const_int 0)])
+			   (match_operand 3 "pc_or_label_operand")
+			   (match_operand 4 "pc_or_label_operand")))]
+  "peep2_reg_dead_p (2, operands[0])
+   && peep2_reg_dead_p (2, operands[2])
+   && (operands[3] == pc_rtx || operands[4] == pc_rtx)
+   && DATA_REG_P (operands[2])
+   && !rtx_equal_p (operands[0], operands[2])"
+  [(set (match_dup 2) (plus:SI (match_dup 2) (match_dup 6)))
+   (set (cc0) (compare (match_dup 2) (const_int 0)))
+   (set (pc) (if_then_else (match_op_dup 5 [(cc0) (const_int 0)])
+			   (match_dup 3)
+			   (match_dup 4)))]
+  "operands[6] = GEN_INT (-INTVAL (operands[1]));")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "pow2_m1_operand" ""))
+   (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+		       (match_operand:SI 3 "register_operand" "")))
+   (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+			   (match_operand 4 "pc_or_label_operand")
+			   (match_operand 5 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   && operands[0] == operands[3]
+   && peep2_reg_dead_p (2, operands[0])
+   && peep2_reg_dead_p (2, operands[2])
+   && (operands[4] == pc_rtx || operands[5] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[2])"
+  [(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
+   (set (cc0) (compare (match_dup 7) (const_int 0)))
+   (set (pc) (if_then_else (ne (cc0) (const_int 0))
+			   (match_dup 4) (match_dup 5)))]
+  "
+{
+  operands[6] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
+  operands[7] = operands[2];
+}")
+
+(define_peephole2
+  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+		       (match_operand:SI 1 "pow2_m1_operand" "")))
+   (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+			   (match_operand 2 "pc_or_label_operand")
+			   (match_operand 3 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   && peep2_reg_dead_p (1, operands[0])
+   && (operands[2] == pc_rtx || operands[3] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[0])"
+  [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
+   (set (cc0) (compare (match_dup 0) (const_int 0)))
+   (set (pc) (if_then_else (ne (cc0) (const_int 0))
+			   (match_dup 2) (match_dup 3)))]
+  "{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "pow2_m1_operand" ""))
+   (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+		       (match_operand:SI 3 "register_operand" "")))
+   (set (pc) (if_then_else (leu (cc0) (const_int 0))
+			   (match_operand 4 "pc_or_label_operand")
+			   (match_operand 5 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   && operands[0] == operands[3]
+   && peep2_reg_dead_p (2, operands[0])
+   && peep2_reg_dead_p (2, operands[2])
+   && (operands[4] == pc_rtx || operands[5] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[2])"
+  [(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
+   (set (cc0) (compare (match_dup 7) (const_int 0)))
+   (set (pc) (if_then_else (eq (cc0) (const_int 0))
+			   (match_dup 4) (match_dup 5)))]
+  "
+{
+  operands[6] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
+  operands[7] = operands[2];
+}")
+(define_peephole2
+  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+		       (match_operand:SI 1 "pow2_m1_operand" "")))
+   (set (pc) (if_then_else (leu (cc0) (const_int 0))
+			   (match_operand 2 "pc_or_label_operand")
+			   (match_operand 3 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   &&  peep2_reg_dead_p (1, operands[0])
+   && (operands[2] == pc_rtx || operands[3] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[0])"
+  [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
+   (set (cc0) (compare (match_dup 0) (const_int 0)))
+   (set (pc) (if_then_else (eq (cc0) (const_int 0))
+			   (match_dup 2) (match_dup 3)))]
+  "{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
+
+;; When optimizing for size or for the original 68000 or 68010, we can
+;; improve some relational tests against 65536 (which get canonicalized
+;; internally against 65535).
+;; The rotate in the output pattern will turn into a swap.
+(define_peephole2
+  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+		       (const_int 65535)))
+   (set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
+			     [(cc0) (const_int 0)])
+			   (match_operand 2 "pc_or_label_operand")
+			   (match_operand 3 "pc_or_label_operand")))]
+  "peep2_reg_dead_p (1, operands[0])
+   && (operands[2] == pc_rtx || operands[3] == pc_rtx)
+   && (optimize_size || TUNE_68000_10)
+   && DATA_REG_P (operands[0])"
+  [(set (match_dup 0) (rotate:SI (match_dup 0) (const_int 16)))
+   (set (cc0) (compare (subreg:HI (match_dup 0) 2) (const_int 0)))
+   (set (pc) (if_then_else (match_op_dup 1 [(cc0) (const_int 0)])
+			   (match_dup 2) (match_dup 3)))]
+  "")