OSDN Git Service

* genoutput.c (validate_insn_operands): New.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.md
index 2244adf..75c5525 100644 (file)
@@ -1,5 +1,6 @@
 ;;- Machine description for GNU compiler, Motorola 68000 Version
-;;  Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+;;  Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999
+;;  Free Software Foundation, Inc.
 
 ;; This file is part of GNU CC.
 
@@ -64,6 +65,9 @@
 ;;- 'K'  all integers EXCEPT -128 .. 127
 ;;- 'L'  -8 .. -1
 ;;- 'M'  all integers EXCEPT -256 .. 255
+;;- 'N'  24 .. 31
+;;- 'O'  16
+;;- 'P'  8 .. 15
 
 ;;- Assembler specs:
 ;;- "%."    size separator ("." or "")                 move%.l d0,d1
 ;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
 ;; be folded while optimizing anyway.
 
-(define_insn "tstdi"
+(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 ""
   [(set (cc0)
        (match_operand:DI 0 "nonimmediate_operand" "am,d"))
    (clobber (match_scratch:SI 1 "=X,d"))
     return \"sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0\";
 }")
 
-(define_insn "tstsi"
+(define_expand "tstsi"
+  [(set (cc0)
+       (match_operand:SI 0 "nonimmediate_operand" ""))]
+  ""
+  "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
   [(set (cc0)
        (match_operand:SI 0 "nonimmediate_operand" "rm"))]
   ""
 
 ;; This can't use an address register, because comparisons
 ;; with address registers as second operand always test the whole word.
-(define_insn "tsthi"
+(define_expand "tsthi"
+  [(set (cc0)
+       (match_operand:HI 0 "nonimmediate_operand" ""))]
+  ""
+  "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
   [(set (cc0)
        (match_operand:HI 0 "nonimmediate_operand" "dm"))]
   ""
   "tst%.w %0")
 
-(define_insn "tstqi"
+(define_expand "tstqi"
+  [(set (cc0)
+       (match_operand:QI 0 "nonimmediate_operand" ""))]
+  ""
+  "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
   [(set (cc0)
        (match_operand:QI 0 "nonimmediate_operand" "dm"))]
   ""
   "TARGET_68881 || TARGET_FPA"
   "
 {
+  m68k_last_compare_had_fp_operands = 1;
   if (TARGET_FPA)
     {
       emit_insn (gen_tstsf_fpa (operands[0]));
   "TARGET_68881 || TARGET_FPA"
   "
 {
+  m68k_last_compare_had_fp_operands = 1;
   if (TARGET_FPA)
     {
       emit_insn (gen_tstsf_fpa (operands[0]));
                   (match_operand:DI 1 "general_operand" "")))
      (clobber (match_dup 2))])]
   ""
-  "operands[2] = gen_reg_rtx (DImode);")
+  "m68k_last_compare_had_fp_operands = 0; operands[2] = gen_reg_rtx (DImode);")
 
 (define_insn ""
   [(set (cc0)
   ""
   "
 {
-  if (flag_pic && symbolic_operand (operands[1], SImode))
+  m68k_last_compare_had_fp_operands = 0;
+  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
          register (a new pseudo, or the final destination if reload_in_progress
          is set).   Then fall through normally */
-      extern rtx legitimize_pic_address();
       rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
       operands[1] = legitimize_pic_address (operands[1], SImode, temp);
     }
 }")
 
-;; A composite of the cmp, cmpa, & cmpi m68000 op codes.
+;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>")
-                (match_operand:SI 1 "general_operand" "mr,Ksr,>")))]
-  ""
+        (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mSr,mSa,>")
+                 (match_operand:SI 1 "general_src_operand" "mSr,mSa,KTr,Ksr,>")))]
+  "!TARGET_5200"
   "*
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
       return \"cmp%.l %d0,%d1\";
 #endif
     }
+  if (ADDRESS_REG_P (operands[0])
+      && GET_CODE (operands[1]) == CONST_INT
+      && INTVAL (operands[1]) < 0x8000
+      && INTVAL (operands[1]) >= -0x8000)
+    {
+#ifdef SGS_CMP_ORDER
+      return \"cmp%.w %0,%1\";
+#else
+      return \"cmp%.w %1,%0\";
+#endif
+    }
+#ifdef SGS_CMP_ORDER
+  return \"cmp%.l %d0,%d1\";
+#else
+  return \"cmp%.l %d1,%d0\";
+#endif
+}")
+
+(define_insn ""
+  [(set (cc0)
+       (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
+                (match_operand:SI 1 "general_operand" "r,mrKs")))]
+  "TARGET_5200"
+  "*
+{
+  if (REG_P (operands[1])
+      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+    { cc_status.flags |= CC_REVERSED;
+#ifdef SGS_CMP_ORDER
+      return \"cmp%.l %d1,%d0\";
+#else
+      return \"cmp%.l %d0,%d1\";
+#endif
+    }
 #ifdef SGS_CMP_ORDER
   return \"cmp%.l %d0,%d1\";
 #else
 #endif
 }")
 
-(define_insn "cmphi"
+(define_expand "cmphi"
+  [(set (cc0)
+        (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
+                 (match_operand:HI 1 "general_src_operand" "")))]
+  "!TARGET_5200"
+  "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
   [(set (cc0)
-       (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
-                (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+        (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>")
+                 (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))]
   "!TARGET_5200"
   "*
 {
 #endif
 }")
 
-(define_insn "cmpqi"
+(define_expand "cmpqi"
+  [(set (cc0)
+        (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
+                 (match_operand:QI 1 "general_src_operand" "")))]
+  "!TARGET_5200"
+  "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
   [(set (cc0)
-       (compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>")
-                (match_operand:QI 1 "general_operand" "dm,nd,>")))]
+        (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>")
+                 (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))]
   "!TARGET_5200"
   "*
 {
   "TARGET_68881 || TARGET_FPA"
   "
 {
+  m68k_last_compare_had_fp_operands = 1;
   if (TARGET_FPA)
     {
       emit_insn (gen_cmpdf_fpa (operands[0], operands[1]));
  "TARGET_68881 || TARGET_FPA"
  "
 {
+  m68k_last_compare_had_fp_operands = 1;
   if (TARGET_FPA)
     {
       emit_insn (gen_cmpsf_fpa (operands[0], operands[1]));
 \f
 ;; Recognizers for btst instructions.
 
+;; Coldfire/5200 only allows "<Q>" type addresses when the bit position is
+;; specified as a constant, so we must disable all patterns that may extract
+;; 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_operand" "o")
+  [(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"))))]
-  ""
+  "!TARGET_5200"
+  "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+;; This is the same as the above pattern except for the constraints.  The 'i'
+;; 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"))))]
+  "TARGET_5200"
   "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
 
 (define_insn ""
   [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
                            (const_int 1)
                            (match_operand:SI 1 "const_int_operand" "n")))]
-  "(unsigned) INTVAL (operands[1]) < 8"
+  "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_5200"
   "*
 {
-  operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1]));
+  operands[1] = GEN_INT (7 - INTVAL (operands[1]));
   return output_btst (operands, operands[1], operands[0], insn, 7);
 }")
 
   [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do")
                            (const_int 1)
                            (match_operand:SI 1 "const_int_operand" "n")))]
-  ""
+  "!TARGET_5200"
+  "*
+{
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      operands[0] = adj_offsettable_operand (operands[0],
+                                            INTVAL (operands[1]) / 8);
+      operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
+      return output_btst (operands, operands[1], operands[0], insn, 7);
+    }
+  operands[1] = GEN_INT (31 - INTVAL (operands[1]));
+  return output_btst (operands, operands[1], operands[0], insn, 31);
+}")
+
+;; This is the same as the above pattern except for the constraints.
+;; 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")))]
+  "TARGET_5200"
   "*
 {
   if (GET_CODE (operands[0]) == MEM)
     {
       operands[0] = adj_offsettable_operand (operands[0],
                                             INTVAL (operands[1]) / 8);
-      operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                            7 - INTVAL (operands[1]) % 8);
+      operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
       return output_btst (operands, operands[1], operands[0], insn, 7);
     }
-  operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                        31 - INTVAL (operands[1]));
+  operands[1] = GEN_INT (31 - INTVAL (operands[1]));
   return output_btst (operands, operands[1], operands[0], insn, 31);
 }")
 
   ""
   "
 {
-  if (flag_pic && symbolic_operand (operands[1], SImode))
+  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
          register (a new pseudo, or the final destination if reload_in_progress
          is set).   Then fall through normally */
-      extern rtx legitimize_pic_address();
       rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
       operands[1] = legitimize_pic_address (operands[1], SImode, temp);
     }
+  else if (flag_pic && TARGET_PCREL && ! reload_in_progress)
+    {
+      /* Don't allow writes to memory except via a register;
+        the m68k doesn't consider PC-relative addresses to be writable.  */
+      if (symbolic_operand (operands[0], SImode))
+       operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+      else if (GET_CODE (operands[0]) == MEM
+              && symbolic_operand (XEXP (operands[0], 0), SImode))
+       operands[0] = gen_rtx (MEM, SImode,
+                              force_reg (SImode, XEXP (operands[0], 0)));
+    }
 }")
 
 ;; General case of fullword move.  The register constraints
   ;; Notes: make sure no alternative allows g vs g.
   ;; We don't allow f-regs since fixed point cannot go in them.
   ;; We do allow y and x regs since fixed point is allowed in them.
-  [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
-       (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
-  ""
+  [(set (match_operand:SI 0 "general_operand" "=g,d,a<,y,!*x*r*m")
+        (match_operand:SI 1 "general_src_operand" "daymSKT,n,i,g,*x*r*m"))]
+
+  "!TARGET_5200"
   "*
 {
-  if (which_alternative == 3)
+  if (which_alternative == 4)
     return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
   if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
     return \"fpmove%.l %x1,%x0\";
-  if (GET_CODE (operands[1]) == CONST_INT)
-    return output_move_simode_const (operands);
-  else if ((GET_CODE (operands[1]) == SYMBOL_REF
-           || GET_CODE (operands[1]) == CONST)
-          && push_operand (operands[0], SImode))
-    return \"pea %a1\";
-  else if ((GET_CODE (operands[1]) == SYMBOL_REF
-           || GET_CODE (operands[1]) == CONST)
-          && ADDRESS_REG_P (operands[0]))
-    return \"lea %a1,%0\";
-  return \"move%.l %1,%0\";
+  return output_move_simode (operands);
 }")
 
-(define_insn "movhi"
-  [(set (match_operand:HI 0 "general_operand" "=g")
-       (match_operand:HI 1 "general_operand" "g"))]
-  ""
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r<Q>,g")
+       (match_operand:SI 1 "general_operand" "g,r<Q>"))]
+  "TARGET_5200"
+  "* return output_move_simode (operands);")
+
+;; Special case of fullword move, where we need to get a non-GOT PIC
+;; reference into an address register.
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=a<")
+        (match_operand:SI 1 "pcrel_address" ""))]
+  "TARGET_PCREL"
   "*
 {
-  if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      if (operands[1] == const0_rtx
-         && (DATA_REG_P (operands[0])
-             || GET_CODE (operands[0]) == MEM)
-         /* clr insns on 68000 read before writing.
-            This isn't so on the 68010, but we have no TARGET_68010.  */
-         && ((TARGET_68020 || TARGET_5200)
-             || !(GET_CODE (operands[0]) == MEM
-                  && MEM_VOLATILE_P (operands[0]))))
-       return \"clr%.w %0\";
-      else if (DATA_REG_P (operands[0])
-              && INTVAL (operands[1]) < 128
-              && INTVAL (operands[1]) >= -128)
-        {
-#if defined(MOTOROLA) && !defined(CRDS)
-          return \"moveq%.l %1,%0\";
-#else
-         return \"moveq %1,%0\";
-#endif
-       }
-      else if (INTVAL (operands[1]) < 0x8000
-              && INTVAL (operands[1]) >= -0x8000)
-       return \"move%.w %1,%0\";
-    }
-  else if (CONSTANT_P (operands[1]))
-    return \"move%.l %1,%0\";
-#ifndef SGS_NO_LI
-  /* Recognize the insn before a tablejump, one that refers
-     to a table of offsets.  Such an insn will need to refer
-     to a label on the insn.  So output one.  Use the label-number
-     of the table of offsets to generate this label.  This code,
-     and similar code below, assumes that there will be at most one
-     reference to each table.  */
-  if (GET_CODE (operands[1]) == MEM
-      && GET_CODE (XEXP (operands[1], 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
-      && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
-    {
-      rtx labelref = XEXP (XEXP (operands[1], 0), 1);
-#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
-#ifdef SGS
-      asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\",
-                  CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#else /* not SGS */
-      asm_fprintf (asm_out_file, \"\\t.set %LLI%d,.+2\\n\",
-                  CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#endif /* not SGS */
-#else /* SGS_SWITCH_TABLES or not MOTOROLA */
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
-                                CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#ifdef SGS_SWITCH_TABLES
-      /* Set flag saying we need to define the symbol
-        LD%n (with value L%n-LI%n) at the end of the switch table.  */
-      switch_table_difference_label_flag = 1;
-#endif /* SGS_SWITCH_TABLES */
-#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
-    }
-#endif /* SGS_NO_LI */
-  return \"move%.w %1,%0\";
+  if (push_operand (operands[0], SImode))
+    return \"pea %a1\";
+  return \"lea %a1,%0\";
 }")
 
-(define_insn "movstricthi"
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "general_operand" "")
+       (match_operand:HI 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=g")
+        (match_operand:HI 1 "general_src_operand" "gS"))]
+  "!TARGET_5200"
+  "* return output_move_himode (operands);")
+
+ (define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=r<Q>,g")
+       (match_operand:HI 1 "general_operand" "g,r<Q>"))]
+  "TARGET_5200"
+  "* return output_move_himode (operands);")
+
+(define_expand "movstricthi"
+  [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
+        (match_operand:HI 1 "general_src_operand" ""))]
+  ""
+  "")
+
+(define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
-       (match_operand:HI 1 "general_operand" "rmn"))]
+       (match_operand:HI 1 "general_src_operand" "rmSn"))]
+  "!TARGET_5200"
+  "* return output_move_stricthi (operands);")
+
+(define_insn ""
+  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+d,m"))
+       (match_operand:HI 1 "general_src_operand" "rmn,r"))]
+  "TARGET_5200"
+  "* return output_move_stricthi (operands);")
+
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "general_operand" "")
+        (match_operand:QI 1 "general_src_operand" ""))]
   ""
-  "*
-{
-  if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      if (operands[1] == const0_rtx
-         && (DATA_REG_P (operands[0])
-             || GET_CODE (operands[0]) == MEM)
-         /* clr insns on 68000 read before writing.
-            This isn't so on the 68010, but we have no TARGET_68010.  */
-         && ((TARGET_68020 || TARGET_5200)
-             || !(GET_CODE (operands[0]) == MEM
-                  && MEM_VOLATILE_P (operands[0]))))
-       return \"clr%.w %0\";
-    }
-  return \"move%.w %1,%0\";
-}")
+  "")
 
-(define_insn "movqi"
+(define_insn ""
   [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
-       (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))]
-  ""
-  "*
-{
-  rtx xoperands[4];
+       (match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
+  "!TARGET_5200"
+  "* return output_move_qimode (operands);")
 
-  /* This is probably useless, since it loses for pushing a struct
-     of several bytes a byte at a time.  */
-  if (GET_CODE (operands[0]) == MEM
-      && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-      && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
-      && ! ADDRESS_REG_P (operands[1]))
-    {
-      xoperands[1] = operands[1];
-      xoperands[2]
-        = gen_rtx (MEM, QImode,
-                  gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
-      /* Just pushing a byte puts it in the high byte of the halfword.  */
-      /* We must put it in the low-order, high-numbered byte.  */
-      output_asm_insn (\"move%.b %1,%-\;move%.b %@,%2\", xoperands);
-      return \"\";
-    }
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=d<Q>,dm,d*a")
+       (match_operand:QI 1 "general_src_operand" "dmi,d<Q>,di*a"))]
+  "TARGET_5200"
+  "* return output_move_qimode (operands);")
 
-  /* clr and st insns on 68000 read before writing.
-     This isn't so on the 68010, but we have no TARGET_68010.  */
-  if (!ADDRESS_REG_P (operands[0])
-      && (TARGET_68020
-         || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
-    {
-      if (operands[1] == const0_rtx)
-       return \"clr%.b %0\";
-      if (GET_CODE (operands[1]) == CONST_INT
-         && (INTVAL (operands[1]) & 255) == 255)
-       {
-         CC_STATUS_INIT;
-         return \"st %0\";
-       }
-    }
-  if (GET_CODE (operands[1]) == CONST_INT
-      && DATA_REG_P (operands[0])
-      && INTVAL (operands[1]) < 128
-      && INTVAL (operands[1]) >= -128)
-    {
-#if defined(MOTOROLA) && !defined(CRDS)
-      return \"moveq%.l %1,%0\";
-#else
-      return \"moveq %1,%0\";
-#endif
-    }
-  if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
-    return \"move%.l %1,%0\";
-  if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
-    return \"move%.w %1,%0\";
-  return \"move%.b %1,%0\";
-}")
+(define_expand "movstrictqi"
+  [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
+        (match_operand:QI 1 "general_src_operand" ""))]
+  ""
+  "")
 
-(define_insn "movstrictqi"
+(define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
-       (match_operand:QI 1 "general_operand" "dmn"))]
+       (match_operand:QI 1 "general_src_operand" "dmSn"))]
+  "!TARGET_5200"
+  "* return output_move_strictqi (operands);")
+
+(define_insn ""
+  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+d,m"))
+       (match_operand:QI 1 "general_src_operand" "dmn,d"))]
+  "TARGET_5200"
+  "* return output_move_strictqi (operands);")
+
+(define_expand "movsf"
+  [(set (match_operand:SF 0 "general_operand" "")
+       (match_operand:SF 1 "general_operand" ""))]
   ""
-  "*
-{
-  if (operands[1] == const0_rtx
-      /* clr insns on 68000 read before writing.
-         This isn't so on the 68010, but we have no TARGET_68010.  */
-      && ((TARGET_68020 || TARGET_5200)
-          || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
-    return \"clr%.b %0\";
-  return \"move%.b %1,%0\";
-}")
+  "")
 
-(define_insn "movsf"
+(define_insn ""
   [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm")
        (match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]
 ;  [(set (match_operand:SF 0 "general_operand" "=rmf")
 ;      (match_operand:SF 1 "general_operand" "rmfF"))]
-  ""
+  "!TARGET_5200"
   "*
 {
   if (which_alternative >= 4)
        return \"fmove%.s %1,%-\;move%.l %+,%0\";
       return \"fmove%.s %f1,%0\";
     }
+  if (operands[1] == CONST0_RTX (SFmode)
+      /* clr insns on 68000 read before writing.
+        This isn't so on the 68010, but we have no TARGET_68010.  */
+      && ((TARGET_68020 || TARGET_5200)
+         || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+    {
+      if (ADDRESS_REG_P (operands[0]))
+       {
+         /* On the '040, 'subl an,an' takes 2 clocks while lea takes only 1 */
+         if (!TARGET_68040 && !TARGET_68060)
+           return \"sub%.l %0,%0\";
+         else
+           {
+#ifdef MOTOROLA
+#ifdef SGS
+             /* Many SGS assemblers croak on size specifiers for constants. */
+             return \"lea 0,%0\";
+#else
+             return \"lea 0.w,%0\";
+#endif
+#else
+             return \"lea 0:w,%0\";
+#endif
+           }
+       }
+      /* moveq is faster on the 68000.  */
+      if (DATA_REG_P (operands[0]) && !(TARGET_68020 || TARGET_5200))
+       {
+#if defined(MOTOROLA) && !defined(CRDS)
+         return \"moveq%.l %#0,%0\";
+#else
+         return \"moveq %#0,%0\";
+#endif
+       }
+      return \"clr%.l %0\";
+    }
   return \"move%.l %1,%0\";
 }")
 
-(define_insn "movdf"
-  [(set (match_operand:DF 0 "general_operand" "=rm,rf,rf,&rof<>,y,rm,x,!x,!rm")
-       (match_operand:DF 1 "general_operand" "rf,m,0,rofE<>,rmE,y,xH,rm,x"))]
+(define_insn ""
+  [(set (match_operand:SF 0 "general_operand" "=r,g")
+       (match_operand:SF 1 "general_operand" "g,r"))]
+  "TARGET_5200"
+  "* return \"move%.l %1,%0\";")
+
+(define_expand "movdf"
+  [(set (match_operand:DF 0 "general_operand" "")
+       (match_operand:DF 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:DF 0 "general_operand"
+                               "=*rm,*rf,*rf,&*rof<>,y,*rm,x,!x,!*rm")
+       (match_operand:DF 1 "general_operand"
+                               "*rf,m,0,*rofE<>,*rmE,y,xH,*rm,x"))]
 ;  [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>")
 ;      (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))]
-  ""
+  "!TARGET_5200"
   "*
 {
   if (which_alternative == 7)
       if (REG_P (operands[1]))
        {
          rtx xoperands[2];
-         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
          output_asm_insn (\"move%.l %1,%-\", xoperands);
          output_asm_insn (\"move%.l %1,%-\", operands);
          return \"f%&move%.d %+,%0\";
       if (REG_P (operands[0]))
        {
          output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
-         operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+         operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
          return \"move%.l %+,%0\";
        }
       else
         return \"fmove%.d %f1,%0\";
     }
   return output_move_double (operands);
-}
-")
+}")
+
+(define_insn ""
+  [(set (match_operand:DF 0 "general_operand" "=r,g")
+       (match_operand:DF 1 "general_operand" "g,r"))]
+  "TARGET_5200"
+  "* return output_move_double (operands);")
 
 (define_expand "movxf"
   [(set (match_operand:XF 0 "nonimmediate_operand" "")
        operands[1] = change_address (operands[1], XFmode,
                                      XEXP (operands[1], 0));
     }
+  if (flag_pic && TARGET_PCREL && ! reload_in_progress)
+    {
+      /* Don't allow writes to memory except via a register;
+        the m68k doesn't consider PC-relative addresses to be writable.  */
+      if (GET_CODE (operands[0]) == MEM
+         && symbolic_operand (XEXP (operands[0], 0), SImode))
+       operands[0] = gen_rtx (MEM, XFmode,
+                              force_reg (SImode, XEXP (operands[0], 0)));
+    }
 }")
 
 (define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,!r,!f")
-       (match_operand:XF 1 "nonimmediate_operand" "m,f,f,f,r"))]
+  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,!r,!f,!r")
+       (match_operand:XF 1 "nonimmediate_operand" "m,f,f,f,r,!r"))]
   "TARGET_68881"
   "*
 {
       if (REG_P (operands[1]))
        {
          rtx xoperands[2];
-         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
          output_asm_insn (\"move%.l %1,%-\", xoperands);
-         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
          output_asm_insn (\"move%.l %1,%-\", xoperands);
          output_asm_insn (\"move%.l %1,%-\", operands);
          return \"fmove%.x %+,%0\";
         return \"fmove%.x %1,%0\";
       return \"fmove%.x %f1,%0\";
     }
-  if (REG_P (operands[0]))
+  if (FP_REG_P (operands[1]))
     {
-      output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands);
-      operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-      output_asm_insn (\"move%.l %+,%0\", operands);
-      operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-      return \"move%.l %+,%0\";
+      if (REG_P (operands[0]))
+       {
+         output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands);
+         operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+         output_asm_insn (\"move%.l %+,%0\", operands);
+         operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+         return \"move%.l %+,%0\";
+       }
+      /* Must be memory destination.  */
+      return \"fmove%.x %f1,%0\";
     }
-  return \"fmove%.x %f1,%0\";
+  return output_move_double (operands);
 }
 ")
 
 (define_insn ""
   [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
        (match_operand:XF 1 "nonimmediate_operand" "rf,m,rof<>"))]
-  "! TARGET_68881"
+  "! TARGET_68881 && ! TARGET_5200"
   "*
 {
   if (FP_REG_P (operands[0]))
       if (REG_P (operands[1]))
        {
          rtx xoperands[2];
-         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
          output_asm_insn (\"move%.l %1,%-\", xoperands);
-         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
          output_asm_insn (\"move%.l %1,%-\", xoperands);
          output_asm_insn (\"move%.l %1,%-\", operands);
          return \"fmove%.x %+,%0\";
       if (REG_P (operands[0]))
         {
           output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands);
-          operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+          operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
           output_asm_insn (\"move%.l %+,%0\", operands);
-          operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+          operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
           return \"move%.l %+,%0\";
         }
       else
 }
 ")
 
+(define_insn ""
+  [(set (match_operand:XF 0 "nonimmediate_operand" "=r,g")
+       (match_operand:XF 1 "nonimmediate_operand" "g,r"))]
+  "! TARGET_68881 && TARGET_5200"
+  "* return output_move_double (operands);")
+
+(define_expand "movdi"
+  ;; Let's see if it really still needs to handle fp regs, and, if so, why.
+  [(set (match_operand:DI 0 "general_operand" "")
+       (match_operand:DI 1 "general_operand" ""))]
+  ""
+  "")
+
 ;; movdi can apply to fp regs in some cases
-(define_insn "movdi"
+(define_insn ""
   ;; Let's see if it really still needs to handle fp regs, and, if so, why.
   [(set (match_operand:DI 0 "general_operand" "=rm,r,&ro<>,y,rm,!*x,!rm")
        (match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]
 ;      (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]
 ;  [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f")
 ;      (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))]
-  ""
+  "!TARGET_5200"
   "*
 {
   if (which_alternative == 8)
       if (REG_P (operands[1]))
        {
          rtx xoperands[2];
-         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
          output_asm_insn (\"move%.l %1,%-\", xoperands);
          output_asm_insn (\"move%.l %1,%-\", operands);
          return \"fmove%.d %+,%0\";
       if (REG_P (operands[0]))
        {
          output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
-         operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+         operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
          return \"move%.l %+,%0\";
        }
       else
         return \"fmove%.d %f1,%0\";
     }
   return output_move_double (operands);
-}
-")
+}")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "general_operand" "=r,g")
+       (match_operand:DI 1 "general_operand" "g,r"))]
+  "TARGET_5200"
+  "* return output_move_double (operands);")
 
 ;; Thus goes after the move instructions
 ;; because the move instructions are better (require no spilling)
 (define_insn "truncsiqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm,d")
        (truncate:QI
-        (match_operand:SI 1 "general_operand" "doJ,i")))]
+        (match_operand:SI 1 "general_src_operand" "doJS,i")))]
   ""
   "*
 {
 (define_insn "trunchiqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm,d")
        (truncate:QI
-        (match_operand:HI 1 "general_operand" "doJ,i")))]
+        (match_operand:HI 1 "general_src_operand" "doJS,i")))]
   ""
   "*
 {
 (define_insn "truncsihi2"
   [(set (match_operand:HI 0 "general_operand" "=dm,d")
        (truncate:HI
-        (match_operand:SI 1 "general_operand" "roJ,i")))]
+        (match_operand:SI 1 "general_src_operand" "roJS,i")))]
   ""
   "*
 {
 \f
 ;; zero extension instructions
 
+(define_insn "zero_extendqidi2"
+  [(set (match_operand:DI 0 "general_operand" "=&d")
+       (zero_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
+  ""
+  "*
+{
+  CC_STATUS_INIT;
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+  return \"moveq %#0,%0\;moveq %#0,%2\;move%.b %1,%2\";
+}")
+
+(define_insn "zero_extendhidi2"
+  [(set (match_operand:DI 0 "general_operand" "=&d")
+       (zero_extend:DI (match_operand:HI 1 "general_operand" "rm")))]
+  ""
+  "*
+{
+  CC_STATUS_INIT;
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+  return \"moveq %#0,%0\;moveq %#0,%2\;move%.w %1,%2\";
+}")
+
 ;; this is the canonical form for (lshiftrt:DI x 32)
 (define_insn "zero_extendsidi2"
-  [(set (match_operand:DI 0 "general_operand" "rm")
+  [(set (match_operand:DI 0 "general_operand" "=rm")
     (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
   ""
   "*
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
     return \"move%.l %1,%0\;clr%.l %0\";
   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
     return \"clr%.l %0\;move%.l %1,%0\";
   else
     operands[2] = adj_offsettable_operand (operands[0], 4);
+  if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
+      || REGNO (operands[1]) != REGNO (operands[2]))
+    output_asm_insn (\"move%.l %1,%2\", operands);
   if (ADDRESS_REG_P (operands[0]))
-    return \"move%.l %1,%2\;sub%.l %0,%0\";
+    return \"sub%.l %0,%0\";
   else
-    return \"move%.l %1,%2\;clr%.l %0\";
+    return \"clr%.l %0\";
 }")
 
 (define_expand "zero_extendhisi2"
 {
   operands[1] = make_safe_from (operands[1], operands[0]);
   if (GET_CODE (operands[0]) == SUBREG)
-    operands[2] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[0]),
-                          SUBREG_WORD (operands[0]));
+    operands[2] = gen_rtx_SUBREG (HImode, SUBREG_REG (operands[0]),
+                                 SUBREG_WORD (operands[0]));
   else
-    operands[2] = gen_rtx (SUBREG, HImode, operands[0], 0);
+    operands[2] = gen_rtx_SUBREG (HImode, operands[0], 0);
 }")
 
 (define_expand "zero_extendqihi2"
 {
   operands[1] = make_safe_from (operands[1], operands[0]);
   if (GET_CODE (operands[0]) == SUBREG)
-    operands[2] = gen_rtx (SUBREG, QImode, SUBREG_REG (operands[0]),
-                          SUBREG_WORD (operands[0]));
+    operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
+                                 SUBREG_WORD (operands[0]));
   else
-    operands[2] = gen_rtx (SUBREG, QImode, operands[0], 0);
+    operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
 }")
 
 (define_expand "zero_extendqisi2"
 {
   operands[1] = make_safe_from (operands[1], operands[0]);
   if (GET_CODE (operands[0]) == SUBREG)
-    operands[2] = gen_rtx (SUBREG, QImode, SUBREG_REG (operands[0]),
-                          SUBREG_WORD (operands[0]));
+    operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
+                                 SUBREG_WORD (operands[0]));
   else
-    operands[2] = gen_rtx (SUBREG, QImode, operands[0], 0);
+    operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
 }")
 \f
 ;; Patterns to recognize zero-extend insns produced by the combiner.
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=do<>,d<")
-       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn ""
   [(set (match_operand:HI 0 "general_operand" "=do<>,d")
-       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+       (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
     {
       if (GET_CODE (operands[1]) == REG
          && REGNO (operands[0]) == REGNO (operands[1]))
-       return \"and%.w %#0xFF,%0\";
+       return (!TARGET_5200 ? \"and%.w %#0xFF,%0\" : \"and%.l %#0xFF,%0\");
       if (reg_mentioned_p (operands[0], operands[1]))
-        return \"move%.b %1,%0\;and%.w %#0xFF,%0\";
+       return (!TARGET_5200 ? \"move%.b %1,%0\;and%.w %#0xFF,%0\" 
+                            : \"move%.b %1,%0\;and%.l %#0xFF,%0\");
       return \"clr%.w %0\;move%.b %1,%0\";
     }
   else if (GET_CODE (operands[0]) == MEM
          == STACK_POINTER_REGNUM)
        {
          output_asm_insn (\"clr%.w %-\", operands);
-         operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
-                                plus_constant (stack_pointer_rtx, 1));
+         operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
+                                    plus_constant (stack_pointer_rtx, 1));
          return \"move%.b %1,%0\";
        }
       else
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=do<>,d")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn "extendqidi2"
   [(set (match_operand:DI 0 "general_operand" "=d")
-       (sign_extend:DI
-        (match_operand:QI 1 "general_operand" "rm")))]
+        (sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
   ""
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (TARGET_68020 || TARGET_5200)
     return \"move%.b %1,%2\;extb%.l %2\;smi %0\;extb%.l %0\";
   else
 (define_insn "extendhidi2"
   [(set (match_operand:DI 0 "general_operand" "=d")
        (sign_extend:DI
-        (match_operand:HI 1 "general_operand" "rm")))]
+        (match_operand:HI 1 "general_src_operand" "rmS")))]
   ""
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (TARGET_68020 || TARGET_5200)
     return \"move%.w %1,%2\;ext%.l %2\;smi %0\;extb%.l %0\";
   else
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (TARGET_68020 || TARGET_5200)
     return \"move%.l %1,%2\;smi %0\;extb%.l %0\";
   else
   "*
 {
   CC_STATUS_INIT;
-  operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (GET_CODE (operands[1]) == CONST_INT
   && (unsigned) INTVAL (operands[1]) > 8)
     {
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "general_operand" "=*d,a")
        (sign_extend:SI
-        (match_operand:HI 1 "nonimmediate_operand" "0,rm")))]
+        (match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))]
   ""
   "*
 {
   if (DATA_REG_P (operands[0]) && FP_REG_P (operands[1]))
     {
       output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
-      operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
       return \"move%.l %+,%0\";
     }
   return \"fmove%.d %f1,%0\";
   ""
   "*
 {
-  operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (REG_P (operands[1]) && REGNO (operands[1]) == REGNO (operands[0]))
     return
     \"move%.l %1,%2\;add%.l %2,%2\;subx%.l %2,%2\;sub%.l %2,%3\;subx%.l %2,%0\";
   if (GET_CODE (operands[1]) == REG)
-    operands[4] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+    operands[4] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC
         || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
     operands[4] = operands[1];
 } ")
 
 (define_insn "adddi_dilshr32"
-  [(set (match_operand:DI 0 "general_operand" "=do")
+  [(set (match_operand:DI 0 "general_operand" "=d,o")
 ;;    (plus:DI (match_operand:DI 2 "general_operand" "%0")
 ;;     (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
 ;;            (const_int 32))))]
-    (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
+    (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,r")
             (const_int 32))
-        (match_operand:DI 2 "general_operand" "0")))]
+        (match_operand:DI 2 "general_operand" "0,0")))]
   ""
   "*
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[2] = adj_offsettable_operand (operands[0], 4);
   return \"add%.l %1,%2\;negx%.l %0\;neg%.l %0\";
 } ")
 
 (define_insn "adddi_dishl32"
-  [(set (match_operand:DI 0 "general_operand" "=ro")
+  [(set (match_operand:DI 0 "general_operand" "=r,o")
 ;;    (plus:DI (match_operand:DI 2 "general_operand" "%0")
 ;;     (ashift:DI (match_operand:DI 1 "general_operand" "ro")
 ;;            (const_int 32))))]
-    (plus:DI (ashift:DI (match_operand:DI 1 "general_operand" "ro")
+    (plus:DI (ashift:DI (match_operand:DI 1 "general_operand" "ro,r")
             (const_int 32))
-        (match_operand:DI 2 "general_operand" "0")))]
+        (match_operand:DI 2 "general_operand" "0,0")))]
   ""
   "*
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[1]) == REG)
-    operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+    operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   else
     operands[1] = adj_offsettable_operand (operands[1], 4);
   return \"add%.l %1,%0\";
 (define_insn "adddi3"
   [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
        (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0")
-                (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+                (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
    (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
   ""
   "*
        return \"add%.l %R2,%R0\;addx%.l %2,%0\";
       else if (GET_CODE (operands[2]) == MEM
          && GET_CODE (XEXP (operands[2], 0)) == POST_INC)
-       {
-         return \"move%.l %2,%3\;add%.l %2,%R0\;addx%.l %3,%0\";
-       }
+       return \"move%.l %2,%3\;add%.l %2,%R0\;addx%.l %3,%0\";
       else
        {
-         /* TODO : this should work also for CONST operands[2] */
+         rtx high, low;
+         rtx xoperands[2];
+
          if (GET_CODE (operands[2]) == REG)
-           operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+           {
+             low = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+             high = operands[2];
+           }
+         else if (CONSTANT_P (operands[2]))
+           split_double (operands[2], &high, &low);
+         else
+           {
+             low = adj_offsettable_operand (operands[2], 4);
+             high = operands[2];
+           }
+
+         operands[1] = low, operands[2] = high;
+         xoperands[0] = operands[3];
+         if (GET_CODE (operands[1]) == CONST_INT
+             && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+           xoperands[1] = GEN_INT (-INTVAL (operands[2]) - 1);
          else
-           operands[1] = adj_offsettable_operand (operands[2], 4);
-         return \"move%.l %2,%3\;add%.l %1,%R0\;addx%.l %3,%0\";
+           xoperands[1] = operands[2];
+
+         output_asm_insn (output_move_simode (xoperands), xoperands);
+         if (GET_CODE (operands[1]) == CONST_INT)
+           {
+             if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8)
+               {
+#ifdef NO_ADDSUB_Q
+                 return \"add%.l %1,%R0\;addx%.l %3,%0\";
+#else
+                 return \"addq%.l %1,%R0\;addx%.l %3,%0\";
+#endif
+               }
+             else if (INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+               {
+                 operands[1] = GEN_INT (-INTVAL (operands[1]));
+#ifdef NO_ADDSUB_Q
+                 return \"sub%.l %1,%R0\;subx%.l %3,%0\";
+#else
+                 return \"subq%.l %1,%R0\;subx%.l %3,%0\";
+#endif
+               }
+           }
+         return \"add%.l %1,%R0\;addx%.l %3,%0\";
        }
     }
   else if (GET_CODE (operands[0]) == MEM)
       CC_STATUS_INIT;
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
        {
-         operands[1] = gen_rtx (MEM, SImode,
-                  gen_rtx (PLUS, VOIDmode, XEXP(operands[0], 0),
-                           gen_rtx (CONST_INT, VOIDmode, -8)));
+         operands[1] = gen_rtx_MEM (SImode,
+                                    plus_constant (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)
          return \"add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0\";
        }
     }
+  else
+    abort ();
 } ")
 
 (define_insn "addsi_lshrsi_31"
   if (GET_CODE (operands[0]) == MEM)
     {
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-        operands[0] = gen_rtx (MEM, SImode, XEXP (XEXP (operands[0], 0), 0));
+        operands[0] = gen_rtx_MEM (SImode, XEXP (XEXP (operands[0], 0), 0));
       else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-        operands[2] = gen_rtx (MEM, SImode, XEXP (XEXP (operands[0], 0), 0));
+        operands[2] = gen_rtx_MEM (SImode, XEXP (XEXP (operands[0], 0), 0));
     }
   output_asm_insn (\"move%.l %1,%0\", operands);
 #ifdef MOTOROLA
 #else
   output_asm_insn (\"add%.l %#1,%2\", operands);
 #endif
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
-                               CODE_LABEL_NUMBER (operands[3]));
-  return \"\";
-}")
-
-;; Note that the middle two alternatives are near-duplicates
-;; in order to handle insns generated by reload.
-;; This is needed since they are not themselves reloaded,
-;; so commutativity won't apply to them.
-(define_insn "addsi3"
-  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
-       (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
-                (match_operand:SI 2 "general_operand" "dIKLs,rJK,a,mrIKLs")))]
-  ""
-  "*
-{
-  if (! operands_match_p (operands[0], operands[1]))
-    {
-      if (!ADDRESS_REG_P (operands[1]))
-       {
-         rtx tmp = operands[1];
-
-         operands[1] = operands[2];
-         operands[2] = tmp;
-       }
-
-      /* These insns can result from reloads to access
-        stack slots over 64k from the frame pointer.  */
-      if (GET_CODE (operands[2]) == CONST_INT
-         && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
-        return \"move%.l %2,%0\;add%.l %1,%0\";
-#ifdef SGS
-      if (GET_CODE (operands[2]) == REG)
-       return \"lea 0(%1,%2.l),%0\";
-      else
-       return \"lea %c2(%1),%0\";
-#else /* not SGS */
-#ifdef MOTOROLA
-      if (GET_CODE (operands[2]) == REG)
-       return \"lea (%1,%2.l),%0\";
-      else
-       return \"lea (%c2,%1),%0\";
-#else /* not MOTOROLA (MIT syntax) */
-      if (GET_CODE (operands[2]) == REG)
-       return \"lea %1@(0,%2:l),%0\";
-      else
-       return \"lea %1@(%c2),%0\";
-#endif /* not MOTOROLA */
-#endif /* not SGS */
-    }
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-#ifndef NO_ADDSUB_Q
-      if (INTVAL (operands[2]) > 0
-         && INTVAL (operands[2]) <= 8)
-       return \"addq%.l %2,%0\";
-      if (INTVAL (operands[2]) < 0
-         && INTVAL (operands[2]) >= -8)
-        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                                - INTVAL (operands[2]));
-         return \"subq%.l %2,%0\";
-       }
-      /* On the CPU32 it is faster to use two addql instructions to
-        add a small integer (8 < N <= 16) to a register.
-        Likewise for subql. */
-      if (TARGET_CPU32 && REG_P (operands[0]))
-       {
-         if (INTVAL (operands[2]) > 8
-             && INTVAL (operands[2]) <= 16)
-           {
-             operands[2] = gen_rtx (CONST_INT, VOIDmode, 
-                                     INTVAL (operands[2]) - 8);
-             return \"addq%.l %#8,%0\;addq%.l %2,%0\";
-           }
-         if (INTVAL (operands[2]) < -8
-             && INTVAL (operands[2]) >= -16)
-           {
-             operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                                     - INTVAL (operands[2]) - 8);
-             return \"subq%.l %#8,%0\;subq%.l %2,%0\";
-           }
-       }
-#endif
-      if (ADDRESS_REG_P (operands[0])
-         && INTVAL (operands[2]) >= -0x8000
-         && INTVAL (operands[2]) < 0x8000)
-       {
-         if (TARGET_68040)
-           return \"add%.w %2,%0\";
-         else
-#ifdef MOTOROLA  
-           return \"lea (%c2,%0),%0\";
-#else
-           return \"lea %0@(%c2),%0\";
-#endif
-       }
-    }
-  return \"add%.l %2,%0\";
+  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+                               CODE_LABEL_NUMBER (operands[3]));
+  return \"\";
 }")
 
+(define_expand "addsi3"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (plus:SI (match_operand:SI 1 "general_operand" "")
+                (match_operand:SI 2 "general_src_operand" "")))]
+  ""
+  "")
+
+;; Note that the middle two alternatives are near-duplicates
+;; in order to handle insns generated by reload.
+;; This is needed since they are not themselves reloaded,
+;; so commutativity won't apply to them.
+(define_insn "*addsi3_internal"
+  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,d,a")
+        (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0")
+                 (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))]
+
+
+  "! TARGET_5200"
+  "* return output_addsi3 (operands);")
+
+(define_insn "*addsi3_5200"
+  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
+       (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
+                (match_operand:SI 2 "general_src_operand" "d,rJK,a,mrIKLs")))]
+  "TARGET_5200"
+  "* return output_addsi3 (operands);")
+
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=a")
        (plus:SI (match_operand:SI 1 "general_operand" "0")
                 (sign_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
   "!TARGET_5200"
   "add%.w %2,%0")
 
 (define_insn "addhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,r")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
-                (match_operand:HI 2 "general_operand" "dn,rmn")))]
+                (match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "*
 {
         which could confuse us.  */
 
       if (INTVAL (operands[2]) >= 32768)
-       operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (operands[2]) - 65536);
+       operands[2] = GEN_INT (INTVAL (operands[2]) - 65536);
 
       if (INTVAL (operands[2]) > 0
          && INTVAL (operands[2]) <= 8)
       if (INTVAL (operands[2]) < 0
          && INTVAL (operands[2]) >= -8)
        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                                - INTVAL (operands[2]));
+         operands[2] = GEN_INT (- INTVAL (operands[2]));
          return \"subq%.w %2,%0\";
        }
       /* On the CPU32 it is faster to use two addqw instructions to
          if (INTVAL (operands[2]) > 8
              && INTVAL (operands[2]) <= 16)
            {
-             operands[2] = gen_rtx (CONST_INT, VOIDmode, 
-                                    INTVAL (operands[2]) - 8);
+             operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
              return \"addq%.w %#8,%0\;addq%.w %2,%0\";
            }
          if (INTVAL (operands[2]) < -8
              && INTVAL (operands[2]) >= -16)
            {
-             operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                                    - INTVAL (operands[2]) - 8);
+             operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
              return \"subq%.w %#8,%0\;subq%.w %2,%0\";
            }
        }
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (plus:HI (match_dup 0)
-                (match_operand:HI 1 "general_operand" "dn,rmn")))]
+                (match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "*
 {
         which could confuse us.  */
 
       if (INTVAL (operands[1]) >= 32768)
-       operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (operands[1]) - 65536);
+       operands[1] = GEN_INT (INTVAL (operands[1]) - 65536);
 
       if (INTVAL (operands[1]) > 0
          && INTVAL (operands[1]) <= 8)
       if (INTVAL (operands[1]) < 0
          && INTVAL (operands[1]) >= -8)
        {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                - INTVAL (operands[1]));
+         operands[1] = GEN_INT (- INTVAL (operands[1]));
          return \"subq%.w %1,%0\";
        }
       /* On the CPU32 it is faster to use two addqw instructions to
          if (INTVAL (operands[1]) > 8
              && INTVAL (operands[1]) <= 16)
            {
-             operands[1] = gen_rtx (CONST_INT, VOIDmode, 
-                                    INTVAL (operands[1]) - 8);
+             operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
              return \"addq%.w %#8,%0\;addq%.w %1,%0\";
            }
          if (INTVAL (operands[1]) < -8
              && INTVAL (operands[1]) >= -16)
            {
-             operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                    - INTVAL (operands[1]) - 8);
+             operands[1] = GEN_INT (- INTVAL (operands[1]) - 8);
              return \"subq%.w %#8,%0\;subq%.w %1,%0\";
            }
        }
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
+       (plus:HI (match_operand:HI 1 "general_src_operand" "dn,rmSn")
                 (match_dup 0)))]
   "!TARGET_5200"
   "*
         which could confuse us.  */
 
       if (INTVAL (operands[1]) >= 32768)
-       operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (operands[1]) - 65536);
+       operands[1] = GEN_INT (INTVAL (operands[1]) - 65536);
 
       if (INTVAL (operands[1]) > 0
          && INTVAL (operands[1]) <= 8)
       if (INTVAL (operands[1]) < 0
          && INTVAL (operands[1]) >= -8)
        {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                - INTVAL (operands[1]));
+         operands[1] = GEN_INT (- INTVAL (operands[1]));
          return \"subq%.w %1,%0\";
        }
       /* On the CPU32 it is faster to use two addqw instructions to
          if (INTVAL (operands[1]) > 8
              && INTVAL (operands[1]) <= 16)
            {
-             operands[1] = gen_rtx (CONST_INT, VOIDmode, 
-                                    INTVAL (operands[1]) - 8);
+             operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
              return \"addq%.w %#8,%0\;addq%.w %1,%0\";
            }
          if (INTVAL (operands[1]) < -8
              && INTVAL (operands[1]) >= -16)
            {
-             operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                    - INTVAL (operands[1]) - 8);
+             operands[1] = GEN_INT (- INTVAL (operands[1]) - 8);
              return \"subq%.w %#8,%0\;subq%.w %1,%0\";
            }
        }
 (define_insn "addqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
-                (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "*
 {
   if (GET_CODE (operands[2]) == CONST_INT)
     {
       if (INTVAL (operands[2]) >= 128)
-       operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (operands[2]) - 256);
+       operands[2] = GEN_INT (INTVAL (operands[2]) - 256);
 
       if (INTVAL (operands[2]) > 0
          && INTVAL (operands[2]) <= 8)
        return \"addq%.b %2,%0\";
       if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8)
        {
-        operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]));
+        operands[2] = GEN_INT (- INTVAL (operands[2]));
         return \"subq%.b %2,%0\";
        }
     }
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (plus:QI (match_dup 0)
-                (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "*
 {
   if (GET_CODE (operands[1]) == CONST_INT)
     {
       if (INTVAL (operands[1]) >= 128)
-       operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (operands[1]) - 256);
+       operands[1] = GEN_INT (INTVAL (operands[1]) - 256);
 
       if (INTVAL (operands[1]) > 0
          && INTVAL (operands[1]) <= 8)
        return \"addq%.b %1,%0\";
       if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
        {
-        operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
+        operands[1] = GEN_INT (- INTVAL (operands[1]));
         return \"subq%.b %1,%0\";
        }
     }
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+       (plus:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                 (match_dup 0)))]
   "!TARGET_5200"
   "*
   if (GET_CODE (operands[1]) == CONST_INT)
     {
       if (INTVAL (operands[1]) >= 128)
-       operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (operands[1]) - 256);
+       operands[1] = GEN_INT (INTVAL (operands[1]) - 256);
 
       if (INTVAL (operands[1]) > 0
          && INTVAL (operands[1]) <= 8)
        return \"addq%.b %1,%0\";
       if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
        {
-        operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
+        operands[1] = GEN_INT (- INTVAL (operands[1]));
         return \"subq%.b %1,%0\";
        }
     }
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[1]) == REG)
-    operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+    operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   else
     operands[1] = adj_offsettable_operand (operands[1], 4);
   return \"sub%.l %1,%0\";
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
        (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0")
-                (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+                (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
    (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
   ""
   "*
        }
       else
        {
-         /* TODO : this should work also for CONST operands[2] */
+         rtx high, low;
+         rtx xoperands[2];
+
          if (GET_CODE (operands[2]) == REG)
-           operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+           {
+             low = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+             high = operands[2];
+           }
+         else if (CONSTANT_P (operands[2]))
+           split_double (operands[2], &high, &low);
+         else
+           {
+             low = adj_offsettable_operand (operands[2], 4);
+             high = operands[2];
+           }
+
+         operands[1] = low, operands[2] = high;
+         xoperands[0] = operands[3];
+         if (GET_CODE (operands[1]) == CONST_INT
+             && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+           xoperands[1] = GEN_INT (-INTVAL (operands[2]) - 1);
          else
-           operands[1] = adj_offsettable_operand (operands[2], 4);
-         return \"move%.l %2,%3\;sub%.l %1,%R0\;subx%.l %3,%0\";
+           xoperands[1] = operands[2];
+
+         output_asm_insn (output_move_simode (xoperands), xoperands);
+         if (GET_CODE (operands[1]) == CONST_INT)
+           {
+             if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8)
+               {
+#ifdef NO_ADDSUB_Q
+                 return \"sub%.l %1,%R0\;subx%.l %3,%0\";
+#else
+                 return \"subq%.l %1,%R0\;subx%.l %3,%0\";
+#endif
+               }
+             else if (INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+               {
+                 operands[1] = GEN_INT (-INTVAL (operands[1]));
+#ifdef NO_ADDSUB_Q
+                 return \"add%.l %1,%R0\;addx%.l %3,%0\";
+#else
+                 return \"addq%.l %1,%R0\;addx%.l %3,%0\";
+#endif
+               }
+           }
+         return \"sub%.l %1,%R0\;subx%.l %3,%0\";
        }
     }
   else if (GET_CODE (operands[0]) == MEM)
       CC_STATUS_INIT;
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
        {
-         operands[1] = gen_rtx (MEM, SImode,
-                  gen_rtx (PLUS, VOIDmode, XEXP(operands[0], 0),
-                           gen_rtx (CONST_INT, VOIDmode, -8)));
+         operands[1]
+           = gen_rtx_MEM (SImode, plus_constant (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)
          return \"sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0\";
        }
     }
+  else
+    abort ();
 } ")
 
 (define_insn "subsi3"
-  [(set (match_operand:SI 0 "general_operand" "=m,r")
-       (minus:SI (match_operand:SI 1 "general_operand" "0,0")
-                 (match_operand:SI 2 "general_operand" "ds,mrs")))]
+  [(set (match_operand:SI 0 "general_operand" "=m,d,a")
+       (minus:SI (match_operand:SI 1 "general_operand" "0,0,0")
+                 (match_operand:SI 2 "general_src_operand" "dT,mSrT,mSrs")))]
   ""
   "sub%.l %2,%0")
 
   [(set (match_operand:SI 0 "general_operand" "=a")
        (minus:SI (match_operand:SI 1 "general_operand" "0")
                  (sign_extend:SI
-                  (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+                  (match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
   "!TARGET_5200"
   "sub%.w %2,%0")
 
 (define_insn "subhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,r")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
-                 (match_operand:HI 2 "general_operand" "dn,rmn")))]
+                 (match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "sub%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (minus:HI (match_dup 0)
-                 (match_operand:HI 1 "general_operand" "dn,rmn")))]
+                 (match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "sub%.w %1,%0")
 
 (define_insn "subqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (minus:QI (match_operand:QI 1 "general_operand" "0,0")
-                 (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                 (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "sub%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (minus:QI (match_dup 0)
-                 (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                 (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "sub%.b %1,%0")
 
 (define_insn "mulhi3"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (mult:HI (match_operand:HI 1 "general_operand" "%0")
-                (match_operand:HI 2 "general_operand" "dmn")))]
+                (match_operand:HI 2 "general_src_operand" "dmSn")))]
   ""
   "*
 {
        (mult:SI (sign_extend:SI
                  (match_operand:HI 1 "nonimmediate_operand" "%0"))
                 (sign_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "dmS"))))]
   ""
   "*
 {
 #endif
 }")
 
-(define_insn "mulsi3"
+(define_expand "mulsi3"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (mult:SI (match_operand:SI 1 "general_operand" "")
+                (match_operand:SI 2 "general_operand" "")))]
+  "TARGET_68020 || TARGET_5200"
+  "")
+
+(define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=d")
        (mult:SI (match_operand:SI 1 "general_operand" "%0")
-                (match_operand:SI 2 "general_operand" "dmsK")))]
-  "TARGET_68020 || TARGET_5200"
+                 (match_operand:SI 2 "general_src_operand" "dmSTK")))]
+
+  "TARGET_68020"
+  "muls%.l %2,%0")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=d")
+       (mult:SI (match_operand:SI 1 "general_operand" "%0")
+                (match_operand:SI 2 "general_operand" "d<Q>")))]
+  "TARGET_5200"
   "muls%.l %2,%0")
 
 (define_insn "umulhisi3"
        (mult:SI (zero_extend:SI
                  (match_operand:HI 1 "nonimmediate_operand" "%0"))
                 (zero_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "dmS"))))]
   ""
   "*
 {
       && floating_exact_log2 (operands[2]) && !TARGET_68040 && !TARGET_68060)
     {
       int i = floating_exact_log2 (operands[2]);
-      operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
+      operands[2] = GEN_INT (i);
       return \"fscale%.l %2,%0\";
     }
   if (REG_P (operands[2]))
 (define_insn "divmodsi4"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (div:SI (match_operand:SI 1 "general_operand" "0")
-               (match_operand:SI 2 "general_operand" "dmsK")))
+               (match_operand:SI 2 "general_src_operand" "dmSTK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (mod:SI (match_dup 1) (match_dup 2)))]
   "TARGET_68020 && !TARGET_5200"
 (define_insn "udivmodsi4"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (udiv:SI (match_operand:SI 1 "general_operand" "0")
-                (match_operand:SI 2 "general_operand" "dmsK")))
+                (match_operand:SI 2 "general_src_operand" "dmSTK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (umod:SI (match_dup 1) (match_dup 2)))]
   "TARGET_68020 && !TARGET_5200"
 (define_insn "divmodhi4"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (div:HI (match_operand:HI 1 "general_operand" "0")
-               (match_operand:HI 2 "general_operand" "dmsK")))
+               (match_operand:HI 2 "general_src_operand" "dmSKT")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (mod:HI (match_dup 1) (match_dup 2)))]
   "!TARGET_5200"
   "*
 {
 #ifdef MOTOROLA
-  output_asm_insn(\"ext%.l %0\;divs%.w %2,%0\", operands);
+  output_asm_insn (\"ext%.l %0\;divs%.w %2,%0\", operands);
 #else
-  output_asm_insn(\"extl %0\;divs %2,%0\", operands);
+  output_asm_insn (\"extl %0\;divs %2,%0\", operands);
 #endif
   if (!find_reg_note(insn, REG_UNUSED, operands[3]))
     {
 (define_insn "udivmodhi4"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (udiv:HI (match_operand:HI 1 "general_operand" "0")
-                (match_operand:HI 2 "general_operand" "dmsK")))
+                (match_operand:HI 2 "general_src_operand" "dmSKT")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (umod:HI (match_dup 1) (match_dup 2)))]
   "!TARGET_5200"
   "*
 {
 #ifdef MOTOROLA
-  output_asm_insn(\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
+  output_asm_insn (\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
 #else
-  output_asm_insn(\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
+  output_asm_insn (\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
 #endif
   if (!find_reg_note(insn, REG_UNUSED, operands[3]))
     {
 \f
 ;; logical-and instructions
 
+;; "anddi3" is mainly here to help combine().
+(define_insn "anddi3"
+  [(set (match_operand:DI 0 "general_operand" "=o,d")
+       (and:DI (match_operand:DI 1 "general_operand" "%0,0")
+               (match_operand:DI 2 "general_operand" "dn,don")))]
+  "!TARGET_5200"
+  "*
+{
+  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] = adj_offsettable_operand (operands[0], 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] = adj_offsettable_operand (operands[0], 4);
+      return \"and%.l %2,%0\;and%.l %R2,%1\";
+    }
+  if (GET_CODE (operands[2]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[2], 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.
 
 (define_expand "andsi3"
-  [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
-       (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+  [(set (match_operand:SI 0 "not_sp_operand" "")
+       (and:SI (match_operand:SI 1 "general_operand" "")
+               (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 (define_insn "andsi3_internal"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+               (match_operand:SI 2 "general_src_operand" "dKT,dmSM")))]
   "!TARGET_5200"
   "*
 {
-  int logval;
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
-      && (DATA_REG_P (operands[0])
-         || offsettable_memref_p (operands[0])))
-    {
-      if (GET_CODE (operands[0]) != REG)
-        operands[0] = adj_offsettable_operand (operands[0], 2);
-      operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                            INTVAL (operands[2]) & 0xffff);
-      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
-      CC_STATUS_INIT;
-      if (operands[2] == const0_rtx)
-        return \"clr%.w %0\";
-      return \"and%.w %2,%0\";
-    }
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
-      && (DATA_REG_P (operands[0])
-          || offsettable_memref_p (operands[0])))
-    {
-      if (DATA_REG_P (operands[0]))
-        {
-          operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
-        }
-      else
-        {
-         operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
-        }
-      /* This does not set condition codes in a standard way.  */
-      CC_STATUS_INIT;
-      return \"bclr %1,%0\";
-    }
-  return \"and%.l %2,%0\";
+  return output_andsi3 (operands);
 }")
 
 (define_insn "andsi3_5200"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "d,dmsK")))]
+               (match_operand:SI 2 "general_src_operand" "d,dmsK")))]
   "TARGET_5200"
   "and%.l %2,%0")
 
 (define_insn "andhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,d")
        (and:HI (match_operand:HI 1 "general_operand" "%0,0")
-               (match_operand:HI 2 "general_operand" "dn,dmn")))]
+               (match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (and:HI (match_dup 0)
-               (match_operand:HI 1 "general_operand" "dn,dmn")))]
+               (match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.w %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (and:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+       (and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "and%.w %1,%0")
 (define_insn "andqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (and:QI (match_operand:QI 1 "general_operand" "%0,0")
-               (match_operand:QI 2 "general_operand" "dn,dmn")))]
+               (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (and:QI (match_dup 0)
-               (match_operand:QI 1 "general_operand" "dn,dmn")))]
+               (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (and:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+       (and:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "and%.b %1,%0")
 \f
 ;; inclusive-or instructions
 
+(define_insn "iordi_zext"
+  [(set (match_operand:DI 0 "general_operand" "=o,d")
+    (ior:DI (zero_extend:DI (match_operand 1 "general_operand" "dn,dmn"))
+        (match_operand:DI 2 "general_operand" "0,0")))]
+  "!TARGET_5200"
+  "*
+{
+  int byte_mode;
+
+  CC_STATUS_INIT;
+  if (GET_CODE (operands[0]) == REG)
+    operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+  else
+    operands[0] = adj_offsettable_operand (operands[0], 4);
+  if (GET_MODE (operands[1]) == SImode)
+    return \"or%.l %1,%0\";
+  byte_mode = (GET_MODE (operands[1]) == QImode);
+  if (GET_CODE (operands[0]) == MEM)
+    operands[0] = adj_offsettable_operand (operands[0], byte_mode ? 3 : 2);
+  if (byte_mode)
+    return \"or%.b %1,%0\";
+  else
+    return \"or%.w %1,%0\";
+}")
+
+;; "iordi3" is mainly here to help combine().
+(define_insn "iordi3"
+  [(set (match_operand:DI 0 "general_operand" "=o,d")
+       (ior:DI (match_operand:DI 1 "general_operand" "%0,0")
+               (match_operand:DI 2 "general_operand" "dn,don")))]
+  "!TARGET_5200"
+  "*
+{
+  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] = adj_offsettable_operand (operands[0], 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,%R0\", 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] = adj_offsettable_operand (operands[0], 4);
+      return \"or%.l %2,%0\;or%.l %R2,%1\";
+    }
+  if (GET_CODE (operands[2]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[2], 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 "general_operand" "")
        (ior:SI (match_operand:SI 1 "general_operand" "")
-               (match_operand:SI 2 "general_operand" "")))]
+               (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 (define_insn "iorsi3_internal"
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
-  "!TARGET_5200"
+                (match_operand:SI 2 "general_src_operand" "dKT,dmSMT")))]
+  "! TARGET_5200"
   "*
 {
-  register int logval;
-  if (GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) >> 16 == 0
-      && (DATA_REG_P (operands[0])
-         || offsettable_memref_p (operands[0])))
-    {
-      if (GET_CODE (operands[0]) != REG)
-        operands[0] = adj_offsettable_operand (operands[0], 2);
-      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
-      CC_STATUS_INIT;
-      return \"or%.w %2,%0\";
-    }
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
-      && (DATA_REG_P (operands[0])
-         || offsettable_memref_p (operands[0])))
-    {
-      if (DATA_REG_P (operands[0]))
-       {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
-       }
-      else
-        {
-         operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
-       }
-      CC_STATUS_INIT;
-      return \"bset %1,%0\";
-    }
-  return \"or%.l %2,%0\";
+  return output_iorsi3 (operands);
 }")
 
 (define_insn "iorsi3_5200"
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "d,dmsK")))]
+               (match_operand:SI 2 "general_src_operand" "d,dmsK")))]
   "TARGET_5200"
   "or%.l %2,%0")
 
 (define_insn "iorhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,d")
        (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
-               (match_operand:HI 2 "general_operand" "dn,dmn")))]
+               (match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (ior:HI (match_dup 0)
-               (match_operand:HI 1 "general_operand" "dn,dmn")))]
+               (match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.w %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (ior:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+       (ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "or%.w %1,%0")
 (define_insn "iorqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
-               (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (ior:QI (match_dup 0)
-               (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (ior:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+        (ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "or%.b %1,%0")
 ;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
 
 (define_insn "iorsi_zexthi_ashl16"
-  [(set (match_operand:SI 0 "general_operand" "=d,d")
-    (ior:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "dmn,dmn"))
-        (ashift:SI (match_operand:SI 2 "general_operand" "o,0")
+  [(set (match_operand:SI 0 "general_operand" "=&d")
+    (ior:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "rmn"))
+        (ashift:SI (match_operand:SI 2 "general_operand" "or")
             (const_int 16))))]
   ""
   "*
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[2]) != REG)
-    {
       operands[2] = adj_offsettable_operand (operands[2], 2);
-      output_asm_insn (\"move%.w %2,%0\", operands);
-    }
+  if (GET_CODE (operands[2]) != REG
+  || REGNO (operands[2]) != REGNO (operands[0]))
+    output_asm_insn (\"move%.w %2,%0\", operands);
   return \"swap %0\;mov%.w %1,%0\";
 }")
 
-(define_insn ""
+(define_insn "iorsi_zext"
   [(set (match_operand:SI 0 "general_operand" "=o,d")
     (ior:SI (zero_extend:SI (match_operand 1 "general_operand" "dn,dmn"))
         (match_operand:SI 2 "general_operand" "0,0")))]
   int byte_mode;
 
   CC_STATUS_INIT;
-  byte_mode = (GET_MODE(operands[1]) == QImode);
+  byte_mode = (GET_MODE (operands[1]) == QImode);
   if (GET_CODE (operands[0]) == MEM)
     operands[0] = adj_offsettable_operand (operands[0], byte_mode ? 3 : 2);
   if (byte_mode)
-       return \"or%.b %1,%0\";
+    return \"or%.b %1,%0\";
   else
-       return \"or%.w %1,%0\";
+    return \"or%.w %1,%0\";
 }")
 \f
 ;; xor instructions
 
+;; "xordi3" is mainly here to help combine().
+(define_insn "xordi3"
+  [(set (match_operand:DI 0 "general_operand" "=od")
+       (xor:DI (match_operand:DI 1 "general_operand" "%0")
+               (match_operand:DI 2 "general_operand" "dn")))]
+  "!TARGET_5200"
+  "*
+{
+  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] = adj_offsettable_operand (operands[0], 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] = adj_offsettable_operand (operands[0], 4);
+      return \"eor%.l %2,%0\;eor%.l %R2,%1\";
+    }
+  if (GET_CODE (operands[2]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[2], 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 "general_operand" "")
        (xor:SI (match_operand:SI 1 "general_operand" "")
 (define_insn "xorsi3_internal"
   [(set (match_operand:SI 0 "general_operand" "=do,m")
        (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "di,dKs")))]
+                (match_operand:SI 2 "general_operand" "di,dKT")))]
+
   "!TARGET_5200"
   "*
 {
-  if (GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) >> 16 == 0
-      && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
-    {
-      if (! DATA_REG_P (operands[0]))
-       operands[0] = adj_offsettable_operand (operands[0], 2);
-      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
-      CC_STATUS_INIT;
-      return \"eor%.w %2,%0\";
-    }
-  return \"eor%.l %2,%0\";
+  return output_xorsi3 (operands);
 }")
 
 (define_insn "xorsi3_5200"
-  [(set (match_operand:SI 0 "general_operand" "=dm")
-       (xor:SI (match_operand:SI 1 "general_operand" "%0")
-               (match_operand:SI 2 "general_operand" "dn")))]
+  [(set (match_operand:SI 0 "general_operand" "=dm,d")
+       (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+               (match_operand:SI 2 "general_operand" "d,Ks")))]
   "TARGET_5200"
   "eor%.l %2,%0")
 
   if (which_alternative == 0)
     return \"neg%.l %0\;negx%.l %0\";
   if (GET_CODE (operands[0]) == REG)
-    operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[1] = adj_offsettable_operand (operands[0], 4);
   if (ADDRESS_REG_P (operands[0]))
   "TARGET_5200"
   "*
 {
-  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   return \"neg%.l %1\;negx%.l %0\";
 } ")
 
       target = operand_subword_force (operands[0], 0, SFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, SFmode),
-                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
 {
   if (DATA_REG_P (operands[0]))
     {
-      operands[1] = gen_rtx (CONST_INT, VOIDmode, 31);
+      operands[1] = GEN_INT (31);
       return \"bchg %1,%0\";
     }
   if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
       target = operand_subword (operands[0], 0, 1, DFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, DFmode),
-                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
 {
   if (DATA_REG_P (operands[0]))
     {
-      operands[1] = gen_rtx (CONST_INT, VOIDmode, 31);
+      operands[1] = GEN_INT (31);
       return \"bchg %1,%0\";
     }
   if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
       target = operand_subword_force (operands[0], 0, SFmode);
       result = expand_binop (SImode, and_optab,
                             operand_subword_force (operands[1], 0, SFmode),
-                            GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword (operands[0], 0, 1, DFmode);
       result = expand_binop (SImode, and_optab,
                             operand_subword_force (operands[1], 0, DFmode),
-                            GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
 \f
 ;; one complement instructions
 
-;; "one_cmpldi2" is only here to help combine().
+;; "one_cmpldi2" is mainly here to help combine().
 (define_insn "one_cmpldi2"
   [(set (match_operand:DI 0 "general_operand" "=dm")
        (not:DI (match_operand:DI 1 "general_operand" "0")))]
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    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];
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[2] = adj_offsettable_operand (operands[0], 4);
   if (ADDRESS_REG_P (operands[0]))
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[1]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+    operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   else
     operands[3] = adj_offsettable_operand (operands[1], 4);
   if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
     return \"clr%.l %0\;move%.l %3,%0\";
   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
   [(set (match_operand:DI 0 "general_operand" "=d")
        (ashift:DI (match_operand:DI 1 "general_operand" "0")
                     (match_operand 2 "const_int_operand" "n")))]
-  "(INTVAL (operands[2]) == 1
-    || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
-   || INTVAL (operands[2]) == 2 || INTVAL (operands[2]) == 3)"
+  "(!TARGET_5200
+    && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+       || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+       || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
   "*
 {
-  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (INTVAL (operands[2]) == 1)
     return \"add%.l %1,%1\;addx%.l %0,%0\";
   else if (INTVAL (operands[2]) == 8)
     return \"rol%.l %#8,%1\;rol%.l %#8,%0\;move%.b %1,%0\;clr%.b %1\";
   else if (INTVAL (operands[2]) == 16)
     return \"swap %1\;swap %0\;move%.w %1,%0\;clr%.w %1\";
+  else if (INTVAL (operands[2]) == 48)
+    return \"mov%.l %1,%0\;swap %0\;clr%.l %1\;clr%.w %0\";
   else if (INTVAL (operands[2]) == 2)
     return \"add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\";
-  else/* if (INTVAL (operands[2]) == 3)*/
+  else if (INTVAL (operands[2]) == 3)
     return \"add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\";
+  else /* 32 < INTVAL (operands[2]) <= 63 */
+    {
+      operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+      output_asm_insn (INTVAL (operands[2]) <= 8 ? \"asl%.l %2,%1\" :
+                       \"moveq %2,%0\;asl%.l %0,%1\", operands);
+      return \"mov%.l %1,%0\;moveq %#0,%1\";
+    }
 } ")
 
 (define_expand "ashldi3"
   [(set (match_operand:DI 0 "general_operand" "")
        (ashift:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand 2 "const_int_operand" "")))]
-  ""
+  "!TARGET_5200"
   "
 {
+  /* ???  This is a named pattern like this is not allowed to FAIL based
+     on its operands.  */
   if (GET_CODE (operands[2]) != CONST_INT
-  || (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 32
-     && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
-     && INTVAL (operands[2]) != 2 && INTVAL (operands[2]) != 3))
+      || ((INTVAL (operands[2]) < 1 || INTVAL (operands[2]) > 3)
+         && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
+         && (INTVAL (operands[2]) < 32 || INTVAL (operands[2]) > 63)))
     FAIL;
 } ")
 
 {
   CC_STATUS_INIT;
 
-  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
   return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\";
 }")
 
   "!TARGET_5200"
   "lsl%.b %1,%0")
 
-;; On all 68k models, this makes faster code in a special case.
+;; On most 68k models, this makes faster code in a special case.
 
 (define_insn "ashrsi_16"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
                     (const_int 16)))]
-  ""
+  "!TARGET_68060"
   "swap %0\;ext%.l %0")
 
 ;; On the 68000, this makes faster code in a special case.
     && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
   "*
 {
-  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
   return \"swap %0\;asr%.w %2,%0\;ext%.l %0\";
 }")
 
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (TARGET_68020)
     return \"move%.l %1,%2\;smi %0\;extb%.l %0\";
   else
   [(set (match_operand:DI 0 "general_operand" "=d")
        (ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
                     (match_operand 2 "const_int_operand" "n")))]
-  "!TARGET_5200 
-    && ((INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
-    || INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8
-    || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 63))"
+  "(!TARGET_5200 
+    && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+       || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+       || INTVAL (operands[2]) == 31
+       || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
   "*
 {
-  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (INTVAL (operands[2]) == 63)
     return \"add%.l %0,%0\;subx%.l %0,%0\;move%.l %0,%1\";
   CC_STATUS_INIT;
     return \"move%.b %0,%1\;asr%.l %#8,%0\;ror%.l %#8,%1\";
   else if (INTVAL (operands[2]) == 16)
     return \"move%.w %0,%1\;clr%.w %0\;swap %1\;ext%.l %0\";
+  else if (INTVAL (operands[2]) == 48)
+    return \"swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0\";
+  else if (INTVAL (operands[2]) == 31)
+    return \"add%.l %1,%1\;addx%.l %0,%0\;move%.l %0,%1\;subx%.l %0,%0\";
   else if (INTVAL (operands[2]) == 2)
     return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\";
-  else/* if (INTVAL (operands[2]) == 3)*/
+  else if (INTVAL (operands[2]) == 3)
     return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\";
+  else /* 32 < INTVAL (operands[2]) <= 63 */
+    {
+      operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+      output_asm_insn (INTVAL (operands[2]) <= 8 ? \"asr%.l %2,%0\" :
+                       \"moveq %2,%1\;asr%.l %1,%0\", operands);
+      output_asm_insn (\"mov%.l %0,%1\;smi %0\", operands);
+      return INTVAL (operands[2]) >= 15 ? \"ext%.w %d0\" :
+            TARGET_68020 ? \"extb%.l %0\" : \"ext%.w %0\;ext%.l %0\";
+    }
 } ")
 
 (define_expand "ashrdi3"
   "!TARGET_5200"
   "
 {
+  /* ???  This is a named pattern like this is not allowed to FAIL based
+     on its operands.  */
   if (GET_CODE (operands[2]) != CONST_INT
-  || (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 2
-     && INTVAL (operands[2]) != 3 && INTVAL (operands[2]) != 8
-     && INTVAL (operands[2]) != 16 && INTVAL (operands[2]) != 32
-     && INTVAL (operands[2]) != 63))
+      || ((INTVAL (operands[2]) < 1 || INTVAL (operands[2]) > 3)
+         && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
+         && (INTVAL (operands[2]) < 31 || INTVAL (operands[2]) > 63)))
     FAIL;
 } ")
 
 ;;  "*
 ;;{
 ;;  if (GET_CODE (operands[1]) == REG)
-;;    operands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+;;    operands[2] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
 ;;  else
 ;;    operands[2] = adj_offsettable_operand (operands[1], 4);
 ;;  return \"move%.l %0,%2\;clr%.l %1\";
   if (which_alternative == 2)
     return \"clr%.l %0\;move%.l %1,%0\";
   if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[2] = adj_offsettable_operand (operands[0], 4);
   if (GET_CODE (operands[1]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+    operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   else
     operands[3] = adj_offsettable_operand (operands[1], 4);
   if (ADDRESS_REG_P (operands[0]))
   [(set (match_operand:DI 0 "general_operand" "=d")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
                     (match_operand 2 "const_int_operand" "n")))]
-  "!TARGET_5200
-    && ((INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
-    || INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8
-    || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 63))"
+  "(!TARGET_5200
+    && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+        || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+        || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
   "*
 {
-  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (INTVAL (operands[2]) == 63)
     return \"add%.l %0,%0\;clr%.l %0\;clr%.l %1\;addx%.l %1,%1\";
   CC_STATUS_INIT;
     return \"move%.b %0,%1\;lsr%.l %#8,%0\;ror%.l %#8,%1\";
   else if (INTVAL (operands[2]) == 16)
     return \"move%.w %0,%1\;clr%.w %0\;swap %1\;swap %0\";
+  else if (INTVAL (operands[2]) == 48)
+    return \"move%.l %0,%1\;clr%.w %1\;clr%.l %0\;swap %1\";
   else if (INTVAL (operands[2]) == 2)
     return \"lsr%.l %#1,%0\;roxr%.l %#1,%1\;lsr%.l %#1,%0\;roxr%.l %#1,%1\";
-  else /*if (INTVAL (operands[2]) == 3)*/
+  else if (INTVAL (operands[2]) == 3)
     return \"lsr%.l %#1,%0\;roxr%.l %#1,%1\;lsr%.l %#1,%0\;roxr%.l %#1,%1\;lsr%.l %#1,%0\;roxr%.l %#1,%1\";
+  else /* 32 < INTVAL (operands[2]) <= 63 */
+    {
+      operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+      output_asm_insn (INTVAL (operands[2]) <= 8 ? \"lsr%.l %2,%0\" :
+                       \"moveq %2,%1\;lsr%.l %1,%0\", operands);
+      return \"mov%.l %0,%1\;moveq %#0,%0\";
+    }
 } ")
 
 (define_expand "lshrdi3"
   "!TARGET_5200"
   "
 {
+  /* ???  This is a named pattern like this is not allowed to FAIL based
+     on its operands.  */
   if (GET_CODE (operands[2]) != CONST_INT
-  || (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 2
-     && INTVAL (operands[2]) != 3 && INTVAL (operands[2]) != 8
-     && INTVAL (operands[2]) != 16 && INTVAL (operands[2]) != 32
-     && INTVAL (operands[2]) != 63))
+      || ((INTVAL (operands[2]) < 1 || INTVAL (operands[2]) > 3)
+         && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
+         && (INTVAL (operands[2]) < 32 || INTVAL (operands[2]) > 63)))
     FAIL;
 } ")
 
   "*
 {
   /* I think lsr%.w sets the CC properly.  */
-  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
   return \"clr%.w %0\;swap %0\;lsr%.w %2,%0\";
 }")
 
 (define_insn "rotlsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (rotate:SI (match_operand:SI 1 "register_operand" "0")
-                  (match_operand:SI 2 "general_operand" "dI")))]
+                  (match_operand:SI 2 "general_operand" "dINO")))]
   "!TARGET_5200"
-  "rol%.l %2,%0")
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)
+    return \"swap %0\";
+  else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16)
+    {
+      operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+      return \"ror%.l %2,%0\";
+    }
+  else
+    return \"rol%.l %2,%0\";
+}")
 
 (define_insn "rotlhi3"
   [(set (match_operand:HI 0 "register_operand" "=d")
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
-                  (match_operand:HI 2 "general_operand" "dI")))]
+                  (match_operand:HI 2 "general_operand" "dIP")))]
   "!TARGET_5200"
-  "rol%.w %2,%0")
-
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+    {
+      operands[2] = GEN_INT (16 - INTVAL (operands[2]));
+      return \"ror%.w %2,%0\";
+    }
+  else
+    return \"rol%.w %2,%0\";
+}")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (rotate:HI (match_dup 0)
-                  (match_operand:HI 1 "general_operand" "dI")))]
+                  (match_operand:HI 1 "general_operand" "dIP")))]
   "!TARGET_5200"
-  "rol%.w %1,%0")
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+    {
+      operands[2] = GEN_INT (16 - INTVAL (operands[2]));
+      return \"ror%.w %2,%0\";
+    }
+  else
+    return \"rol%.w %2,%0\";
+}")
 
 (define_insn "rotlqi3"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (rotate:QI (match_operand:QI 1 "register_operand" "0")
                   (match_operand:QI 2 "general_operand" "dI")))]
   "!TARGET_5200"
-  "rol%.b %2,%0")
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+    {
+      operands[2] = GEN_INT (8 - INTVAL (operands[2]));
+      return \"ror%.b %2,%0\";
+    }
+  else
+    return \"rol%.b %2,%0\";
+}")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
        (rotate:QI (match_dup 0)
                   (match_operand:QI 1 "general_operand" "dI")))]
   "!TARGET_5200"
-  "rol%.b %1,%0")
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+    {
+      operands[2] = GEN_INT (8 - INTVAL (operands[2]));
+      return \"ror%.b %2,%0\";
+    }
+  else
+    return \"rol%.b %2,%0\";
+}")
 
 (define_insn "rotrsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
 (define_insn ""
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
                         (const_int 32)
-                        (match_operand:SI 2 "const_int_operand" "n"))
-       (match_operand:SI 3 "general_operand" "rmi"))]
+                        (match_operand:SI 1 "const_int_operand" "n"))
+       (match_operand:SI 2 "general_src_operand" "rmSi"))]
   "TARGET_68020 && TARGET_BITFIELD
-   && (INTVAL (operands[2]) % 8) == 0
+   && (INTVAL (operands[1]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[0], 0))"
   "*
 {
   operands[0]
-    = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+    = adj_offsettable_operand (operands[0], INTVAL (operands[1]) / 8);
 
-  return \"move%.l %3,%0\";
+  return \"move%.l %2,%0\";
 }")
 
 (define_insn ""
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
+       (zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
                         (const_int 32)
-                        (match_operand:SI 3 "const_int_operand" "n")))]
+                        (match_operand:SI 2 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
-   && (INTVAL (operands[3]) % 8) == 0
+   && (INTVAL (operands[2]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[1], 0))"
   "*
 {
   operands[1]
-    = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+    = adj_offsettable_operand (operands[1], INTVAL (operands[2]) / 8);
 
   return \"move%.l %1,%0\";
 }")
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+       (sign_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
                         (const_int 32)
-                        (match_operand:SI 3 "const_int_operand" "n")))]
+                        (match_operand:SI 2 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
-   && (INTVAL (operands[3]) % 8) == 0
+   && (INTVAL (operands[2]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[1], 0))"
   "*
 {
   operands[1]
-    = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+    = adj_offsettable_operand (operands[1], INTVAL (operands[2]) / 8);
 
   return \"move%.l %1,%0\";
 }")
     {
       int width = GET_CODE (operands[0]) == REG ? 31 : 7;
       return output_btst (operands,
-                         gen_rtx (CONST_INT, VOIDmode,
-                                  width - INTVAL (operands[2])),
-                         operands[0],
-                         insn, 1000);
+                         GEN_INT (width - INTVAL (operands[2])),
+                         operands[0], insn, 1000);
       /* Pass 1000 as SIGNPOS argument so that btst will
          not think we are testing the sign bit for an `and'
         and assume that nonzero implies a negative result.  */
       && GET_CODE (operands[2]) == CONST_INT)
     {
       int width = GET_CODE (operands[0]) == REG ? 31 : 7;
-      return output_btst (operands,
-                         gen_rtx (CONST_INT, VOIDmode,
-                                  width - INTVAL (operands[2])),
-                         operands[0],
-                         insn, 1000);
+      return output_btst (operands, GEN_INT (width - INTVAL (operands[2])),
+                         operands[0], insn, 1000);
       /* Pass 1000 as SIGNPOS argument so that btst will
          not think we are testing the sign bit for an `and'
         and assume that nonzero implies a negative result.  */
   [(set (match_operand:QI 0 "general_operand" "=dm")
     (match_operator 1 "valid_dbcc_comparison_p"
       [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
-  ""
+  "! TARGET_5200"
+  "*
+{
+  return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+} ")
+
+(define_insn "scc0_di_5200"
+  [(set (match_operand:QI 0 "general_operand" "=d")
+    (match_operator 1 "valid_dbcc_comparison_p"
+      [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
+  "TARGET_5200"
+  "*
+{
+  return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+} ")
+
+(define_insn "scc_di"
+  [(set (match_operand:QI 0 "general_operand" "=dm,dm")
+    (match_operator 1 "valid_dbcc_comparison_p"
+      [(match_operand:DI 2 "general_operand" "ro,r")
+       (match_operand:DI 3 "general_operand" "r,ro")]))]
+  "! TARGET_5200"
   "*
 {
-  return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+  return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
 } ")
 
-(define_insn "scc_di"
-  [(set (match_operand:QI 0 "general_operand" "=dm,dm")
+(define_insn "scc_di_5200"
+  [(set (match_operand:QI 0 "general_operand" "=d,d")
     (match_operator 1 "valid_dbcc_comparison_p"
       [(match_operand:DI 2 "general_operand" "ro,r")
        (match_operand:DI 3 "general_operand" "r,ro")]))]
-  ""
+  "TARGET_5200"
   "*
 {
   return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
 } ")
 
-(define_insn "seq"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+;; Note that operand 0 of an SCC insn is supported in the hardware as
+;; 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 (TARGET_68060 && 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_insn "sne"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_expand "sne"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (ne:QI (cc0) (const_int 0)))]
+  ""
+  "
+{
+  if (TARGET_68060 && 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_insn "sgt"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_expand "sgt"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (gt:QI (cc0) (const_int 0)))]
+  ""
+  "
+{
+  if (TARGET_68060 && 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_insn "sgtu"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_expand "sgtu"
+  [(set (match_operand:QI 0 "register_operand" "")
        (gtu:QI (cc0) (const_int 0)))]
   ""
-  "* cc_status = cc_prev_status;
-     return \"shi %0\"; ")
+  "")
 
-(define_insn "slt"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=d")
+       (gtu:QI (cc0) (const_int 0)))]
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"shi %0\"; ")
+
+(define_expand "slt"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (lt:QI (cc0) (const_int 0)))]
+  ""
+  "
+{
+  if (TARGET_68060 && 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)))]
   ""
-  "* cc_status = cc_prev_status;
-     OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
+  "*
+   cc_status = cc_prev_status;
+   OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
 
-(define_insn "sltu"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_expand "sltu"
+  [(set (match_operand:QI 0 "register_operand" "")
        (ltu:QI (cc0) (const_int 0)))]
   ""
-  "* cc_status = cc_prev_status;
-     return \"scs %0\"; ")
+  "")
 
-(define_insn "sge"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=d")
+       (ltu:QI (cc0) (const_int 0)))]
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"scs %0\"; ")
+
+(define_expand "sge"
+  [(set (match_operand:QI 0 "register_operand" "")
        (ge:QI (cc0) (const_int 0)))]
   ""
-  "* cc_status = cc_prev_status;
-     OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+  "
+{
+  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+    {
+      m68k_last_compare_had_fp_operands = 0;
+      FAIL;
+    }
+}")
 
-(define_insn "sgeu"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=d")
+       (ge:QI (cc0) (const_int 0)))]
+  ""
+  "*
+   cc_status = cc_prev_status;
+   OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+
+(define_expand "sgeu"
+  [(set (match_operand:QI 0 "register_operand" "")
        (geu:QI (cc0) (const_int 0)))]
   ""
-  "* cc_status = cc_prev_status;
-     return \"scc %0\"; ")
+  "")
 
-(define_insn "sle"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=d")
+       (geu:QI (cc0) (const_int 0)))]
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"scc %0\"; ")
+
+(define_expand "sle"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (le:QI (cc0) (const_int 0)))]
+  ""
+  "
+{
+  if (TARGET_68060 && 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_insn "sleu"
-  [(set (match_operand:QI 0 "general_operand" "=dm")
+(define_expand "sleu"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (leu:QI (cc0) (const_int 0)))]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (leu:QI (cc0) (const_int 0)))]
   ""
-  "* cc_status = cc_prev_status;
-     return \"sls %0\"; ")
+  "*
+   cc_status = cc_prev_status;
+   return \"sls %0\"; ")
 \f
 ;; Basic conditional jump instructions.
 
 #endif
     }
   if (GET_CODE (operands[0]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[3] = adj_offsettable_operand (operands[0], 4);
   if (! ADDRESS_REG_P (operands[0]))
+    {
+      if (reg_overlap_mentioned_p (operands[2], operands[0]))
+       {
+         if (reg_overlap_mentioned_p (operands[2], operands[3]))
+           {
+#ifdef MOTOROLA
+             return \"or%.l %0,%2\;jbeq %l1\";
+#else
+             return \"or%.l %0,%2\;jeq %l1\";
+#endif
+           }
+         else
+           {
+#ifdef MOTOROLA
+             return \"or%.l %3,%2\;jbeq %l1\";
+#else
+             return \"or%.l %3,%2\;jeq %l1\";
+#endif
+           }
+       }
 #ifdef MOTOROLA
-    return \"move%.l %0,%2\;or%.l %3,%2\;jbeq %l1\";
+      return \"move%.l %0,%2\;or%.l %3,%2\;jbeq %l1\";
 #else
-    return \"move%.l %0,%2\;or%.l %3,%2\;jeq %l1\";
+      return \"move%.l %0,%2\;or%.l %3,%2\;jeq %l1\";
 #endif
+    }
   operands[4] = gen_label_rtx();
+  if (TARGET_68020 || TARGET_5200)
+    {
+#ifdef MOTOROLA
+      output_asm_insn (\"tst%.l %0\;jbne %l4\;tst%.l %3\;jbeq %l1\", operands);
+#else
+      output_asm_insn (\"tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1\", operands);
+#endif
+    }
+  else
+    {
 #ifdef MOTOROLA
-  output_asm_insn (\"tst%.l %0\;jbne %l4\;tst%.l %3\;jbeq %l1\", operands);
+#ifdef SGS_CMP_ORDER
+      output_asm_insn (\"cmp%.w %0,%#0\;jbne %l4\;cmp%.w %3,%#0\;jbeq %l1\", operands);
+#else
+      output_asm_insn (\"cmp%.w %#0,%0\;jbne %l4\;cmp%.w %#0,%3\;jbeq %l1\", operands);
+#endif
 #else
-  output_asm_insn (\"tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1\", operands);
+      output_asm_insn (\"cmp%.w %#0,%0\;jne %l4\;cmp%.w %#0,%3\;jeq %l1\", operands);
 #endif
+    }
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                                CODE_LABEL_NUMBER (operands[4]));
   return \"\";
     }
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[3] = adj_offsettable_operand (operands[0], 4);
-  if (ADDRESS_REG_P (operands[0]))
+  if (!ADDRESS_REG_P (operands[0]))
+    {
+      if (reg_overlap_mentioned_p (operands[2], operands[0]))
+       {
+         if (reg_overlap_mentioned_p (operands[2], operands[3]))
+           {
+#ifdef MOTOROLA
+             return \"or%.l %0,%2\;jbne %l1\";
+#else
+             return \"or%.l %0,%2\;jne %l1\";
+#endif
+           }
+         else
+           {
+#ifdef MOTOROLA
+             return \"or%.l %3,%2\;jbne %l1\";
+#else
+             return \"or%.l %3,%2\;jne %l1\";
+#endif
+           }
+       }
 #ifdef MOTOROLA
-    return \"tst%.l %0\;jbne %l1\;tst%.l %3\;jbne %l1\";
+      return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\";
 #else
-    return \"tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1\";
+      return \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\";
 #endif
+    }
+  if (TARGET_68020 || TARGET_5200)
+    {
+#ifdef MOTOROLA
+      return \"tst%.l %0\;jbne %l1\;tst%.l %3\;jbne %l1\";
+#else
+      return \"tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1\";
+#endif
+    }
   else
+    {
 #ifdef MOTOROLA
-    return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\";
+#ifdef SGS_CMP_ORDER
+      return \"cmp%.w %0,%#0\;jbne %l1\;cmp%.w %3,%#0\;jbne %l1\";
+#else
+      return \"cmp%.w %#0,%0\;jbne %l1\;cmp%.w %#0,%3\;jbne %l1\";
+#endif
 #else
-    return \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\";
+      return \"cmp%.w %#0,%0\;jne %l1\;cmp%.w %#0,%3\;jne %l1\";
 #endif
+    }
 } ")
 
 (define_insn "bge0_di"
        }
     }
   CC_STATUS_INIT;
+  if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+    output_asm_insn(\"tst%.l %0\", operands);
+  else
+    {
+      /* On an address reg, cmpw may replace cmpl.  */
+#ifdef SGS_CMP_ORDER
+      output_asm_insn(\"cmp%.w %0,%#0\", operands);
+#else
+      output_asm_insn(\"cmp%.w %#0,%0\", operands);
+#endif
+    }
+
 #ifdef MOTOROLA
-  return \"tst%.l %0\;jbpl %l1\";
+  return \"jbpl %l1\";
 #else
-  return \"tst%.l %0\;jpl %l1\";
+  return \"jpl %l1\";
 #endif
 } ")
 
        }
     }
   CC_STATUS_INIT;
+  if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+    output_asm_insn(\"tst%.l %0\", operands);
+  else
+    {
+      /* On an address reg, cmpw may replace cmpl.  */
+#ifdef SGS_CMP_ORDER
+      output_asm_insn(\"cmp%.w %0,%#0\", operands);
+#else
+      output_asm_insn(\"cmp%.w %#0,%0\", operands);
+#endif
+    }
+
 #ifdef MOTOROLA
-  return \"tst%.l %0\;jbmi %l1\";
+  return \"jbmi %l1\";
 #else
-  return \"tst%.l %0\;jmi %l1\";
+  return \"jmi %l1\";
 #endif
 } ")
 
   "
 {
 #ifdef CASE_VECTOR_PC_RELATIVE
-    operands[0] = gen_rtx (PLUS, SImode, pc_rtx,
-                          gen_rtx (SIGN_EXTEND, SImode, operands[0]));
+    operands[0] = gen_rtx_PLUS (SImode, pc_rtx,
+                               gen_rtx_SIGN_EXTEND (SImode, operands[0]));
 #endif
 }")
 
 #else
 #ifdef SGS
 #ifdef ASM_OUTPUT_CASE_LABEL
-  return \"jmp 6(%%pc,%0.w)\";
+  if (TARGET_5200) 
+    return \"ext%.l %0\;jmp 6(%%pc,%0.l)\";
+  else
+    return \"jmp 6(%%pc,%0.w)\";
+#else
+  if (TARGET_5200)
+    {
+#ifdef CRDS
+      return \"ext%.l %0\;jmp 2(pc,%0.l)\";
 #else
+      return \"extl %0\;jmp 2(%%pc,%0.l)\";
+#endif  /* end !CRDS */
+    }
+  else
+    {
 #ifdef CRDS
-  return \"jmp 2(pc,%0.w)\";
+      return \"jmp 2(pc,%0.w)\";
 #else
-  return \"jmp 2(%%pc,%0.w)\";
+      return \"jmp 2(%%pc,%0.w)\";
 #endif  /* end !CRDS */
+    }
 #endif
 #else /* not SGS */
+  if (TARGET_5200)
+    {
 #ifdef MOTOROLA
-  return \"jmp (2,pc,%0.w)\";
+      return \"ext%.l %0\;jmp (2,pc,%0.l)\";
 #else
-  return \"jmp pc@(2,%0:w)\";
+      return \"extl %0\;jmp pc@(2,%0:l)\";
 #endif
+    }
+  else
+    {
+#ifdef MOTOROLA
+      return \"jmp (2,pc,%0.w)\";
+#else
+      return \"jmp pc@(2,%0:w)\";
+#endif
+    }
 #endif
 #endif
 ")
   "*
   if (GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+    {
+      if (TARGET_PCREL) return \"bsr.l %o0\";
 #ifdef MOTOROLA
 #ifdef HPUX_ASM
-    return \"bsr.l %0\";
+      return \"bsr.l %0\";
 #else
 #ifdef USE_GAS
-    return \"bsr.l %0@PLTPC\";
+      return \"bsr.l %0@PLTPC\";
 #else
-    return \"bsr %0@PLTPC\";
+      return \"bsr %0@PLTPC\";
 #endif
 #endif
 #else
-    /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
-       GAS just plain ignores it.  */
-    return \"jbsr %0,a1\";
+#ifdef USE_GAS
+      return \"bsr.l %0\";
+#else
+      /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
+        GAS just plain ignores it.  FIXME: not anymore, gas doesnt!  */
+      return \"jbsr %0,a1\";
 #endif
+#endif
+    }
   return \"jsr %0\";
 ")
 
   "*
   if (GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+    {
+      if (TARGET_PCREL) return \"bsr.l %o1\";
 #ifdef MOTOROLA
 #ifdef HPUX_ASM
-    return \"bsr.l %1\";
+      return \"bsr.l %1\";
 #else
 #ifdef USE_GAS
-    return \"bsr.l %1@PLTPC\";
+      return \"bsr.l %1@PLTPC\";
 #else
-    return \"bsr %1@PLTPC\";
+      return \"bsr %1@PLTPC\";
 #endif
 #endif
 #else
-    /* The ',a1' is a dummy argument telling the Sun assembler we want PIC
-       GAS just plain ignores it.  */
-    return \"jbsr %1,a1\";
+#ifdef USE_GAS
+      return \"bsr.l %1\";
+#else
+      /* The ',a1' is a dummy argument telling the Sun assembler we want PIC
+         GAS just plain ignores it.  FIXME: Not anymore, gas doesnt!  */
+      return \"jbsr %1,a1\";
+#endif
 #endif
+    }
   return \"jsr %1\";
 ")
 
 {
   int i;
 
-  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
  "NEED_PROBE"
  "*
 {
-  operands[0] = gen_rtx (PLUS, SImode, stack_pointer_rtx,
-                        gen_rtx (CONST_INT, VOIDmode, NEED_PROBE));
+  operands[0] = plus_constant (stack_pointer_rtx, NEED_PROBE);
   return \"tstl %a0\";
 }")
 
 {
   if (current_function_pops_args == 0)
     return \"rts\";
-  operands[0] = gen_rtx (CONST_INT, VOIDmode, current_function_pops_args);
+  operands[0] = GEN_INT (current_function_pops_args);
   return \"rtd %0\";
 }")
 
   "*
 {
   rtx xoperands[2];
-  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   output_asm_insn (\"move%.l %1,%@\", xoperands);
   output_asm_insn (\"move%.l %1,%-\", operands);
   return \"fmove%.d %+,%0\";
     {
       rtx xoperands[2];
       xoperands[0] = stack_pointer_rtx;
-      xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
+      xoperands[1] = GEN_INT (INTVAL (operands[0]) - 4);
 #ifndef NO_ADDSUB_Q
       if (INTVAL (xoperands[1]) <= 8)
        {
          else
            output_asm_insn (\"addq%.l %1,%0\", xoperands);
        }
-      else if (INTVAL (xoperands[1]) <= 16 
-              && TARGET_68020 && !TARGET_68040 && !TARGET_68060)
+      else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16) 
        {
-         xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                 INTVAL (xoperands[1]) - 8);
+         xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
          output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
        }
       else
 #endif
-        if (INTVAL (xoperands[1]) <= 0x7FFF && !TARGET_5200)
-          output_asm_insn (\"add%.w %1,%0\", xoperands);
+        if (INTVAL (xoperands[1]) <= 0x7FFF)
+        {
+         if (TARGET_68040)
+           output_asm_insn (\"add%.w %1,%0\", xoperands);
+         else
+#ifdef MOTOROLA  
+           output_asm_insn (\"lea (%c1,%0),%0\", xoperands);
+#else
+           output_asm_insn (\"lea %0@(%c1),%0\", xoperands);
+#endif
+        }
       else
         output_asm_insn (\"add%.l %1,%0\", xoperands);
     }
     {
       rtx xoperands[2];
       xoperands[0] = stack_pointer_rtx;
-      xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
+      xoperands[1] = GEN_INT (INTVAL (operands[0]) - 4);
 #ifndef NO_ADDSUB_Q
       if (INTVAL (xoperands[1]) <= 8)
        {
          else
            output_asm_insn (\"addq%.l %1,%0\", xoperands);
        }
-      else if (INTVAL (xoperands[1]) <= 16 
-              && TARGET_68020 && !TARGET_68040 && !TARGET_68060)
+      else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
        {
-         xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                 INTVAL (xoperands[1]) - 8);
+         xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
          output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
        }
       else
 #endif
-        if (INTVAL (xoperands[1]) <= 0x7FFF && !TARGET_5200)
-          output_asm_insn (\"add%.w %1,%0\", xoperands);
+        if (INTVAL (xoperands[1]) <= 0x7FFF)
+        {
+         if (TARGET_68040)
+           output_asm_insn (\"add%.w %1,%0\", xoperands);
+         else
+           {
+#ifdef MOTOROLA  
+             output_asm_insn (\"lea (%c1,%0),%0\", xoperands);
+#else
+             output_asm_insn (\"lea %0@(%c1),%0\", xoperands);
+#endif
+           }
+        }
       else
         output_asm_insn (\"add%.l %1,%0\", xoperands);
     }
 
   xoperands[1] = operands[1];
   xoperands[2]
-    = gen_rtx (MEM, QImode,
-              gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
-                       gen_rtx (CONST_INT, VOIDmode, 3)));
+    = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, 3));
   xoperands[3] = stack_pointer_rtx;
   if (!TARGET_5200)
     output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
    fpsm%.s %x3,%2,%x1,%0
    fpsm%.s %x3,%2,%x1,%0")
 
-(define_insn "tstxf"
+(define_expand "tstxf"
+  [(set (cc0)
+       (match_operand:XF 0 "nonimmediate_operand" ""))]
+  "TARGET_68881"
+  "m68k_last_compare_had_fp_operands = 1;")
+
+(define_insn ""
   [(set (cc0)
        (match_operand:XF 0 "nonimmediate_operand" "fm"))]
   "TARGET_68881"
   return \"ftst%.x %0\";
 }")
 
-(define_insn "cmpxf"
+(define_expand "cmpxf"
+  [(set (cc0)
+       (compare (match_operand:XF 0 "nonimmediate_operand" "")
+                (match_operand:XF 1 "nonimmediate_operand" "")))]
+  "TARGET_68881"
+  "m68k_last_compare_had_fp_operands = 1;")
+
+(define_insn ""
   [(set (cc0)
        (compare (match_operand:XF 0 "nonimmediate_operand" "f,m")
                 (match_operand:XF 1 "nonimmediate_operand" "fm,f")))]
 
 (define_insn "extendsfxf2"
   [(set (match_operand:XF 0 "general_operand" "=fm,f")
-       (float_extend:XF (match_operand:SF 1 "general_operand" "f,m")))]
+       (float_extend:XF (match_operand:SF 1 "general_operand" "f,rmF")))]
   "TARGET_68881"
   "*
 {
       return \"f%$move%.x %1,%0\";
     }
   if (FP_REG_P (operands[0]))
-    return \"f%$move%.s %f1,%0\";
+    {
+      if (FP_REG_P (operands[1]))
+       return \"f%$move%.x %1,%0\";
+      else if (ADDRESS_REG_P (operands[1]))
+       return \"move%.l %1,%-\;f%$move%.s %+,%0\";
+      else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_single (operands);
+      return \"f%$move%.s %f1,%0\";
+    }
   return \"fmove%.x %f1,%0\";
 }")
 
 (define_insn "extenddfxf2"
   [(set (match_operand:XF 0 "general_operand" "=fm,f")
        (float_extend:XF
-          (match_operand:DF 1 "general_operand" "f,m")))]
+          (match_operand:DF 1 "general_operand" "f,rmE")))]
   "TARGET_68881"
   "*
 {
       return \"fmove%.x %1,%0\";
     }
   if (FP_REG_P (operands[0]))
-    return \"f%&move%.d %f1,%0\";
+    {
+      if (REG_P (operands[1]))
+       {
+         rtx xoperands[2];
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+         output_asm_insn (\"move%.l %1,%-\", xoperands);
+         output_asm_insn (\"move%.l %1,%-\", operands);
+         return \"f%&move%.d %+,%0\";
+       }
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_double (operands);
+      return \"f%&move%.d %f1,%0\";
+    }
   return \"fmove%.x %f1,%0\";
 }")
 
   if (REG_P (operands[0]))
     {
       output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
-      operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
       return \"move%.l %+,%0\";
     }
   return \"fmove%.d %f1,%0\";
       target = operand_subword (operands[0], 0, 1, XFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, XFmode),
-                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword (operands[0], 0, 1, XFmode);
       result = expand_binop (SImode, and_optab,
                             operand_subword_force (operands[1], 0, XFmode),
-                            GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
        (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
   "TARGET_68881 && flag_fast_math"
   "fcos%.x %1,%0")
+
+(define_insn "trap"
+  [(trap_if (const_int -1) (const_int 7))]
+  ""
+  "trap %#7")
+
+(define_insn "conditional_trap"
+  [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
+                           [(cc0) (const_int 0)])
+           (match_operand:SI 1 "const_int_operand" "I"))]
+  "TARGET_68020 && ! flags_in_68881 ()"
+  "*
+{
+  switch (GET_CODE (operands[0]))
+  {
+  case EQ:  return \"trapeq\";
+  case NE:  return \"trapne\";
+  case GT:  return \"trapgt\";
+  case GTU: return \"traphi\";
+  case LT:  return \"traplt\";
+  case LTU: return \"trapcs\";
+  case GE:  return \"trapge\";
+  case GEU: return \"trapcc\";
+  case LE:  return \"traple\";
+  case LEU: return \"trapls\";
+  default: abort();
+  }
+}")