OSDN Git Service

(movqi+2): Add address registers.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.md
index e16004e..d2e18e7 100644 (file)
@@ -1,5 +1,5 @@
 ;;- Machine description for GNU compiler, Motorola 68000 Version
-;;  Copyright (C) 1987, 1988, 1993, 1994, 1995 Free Software Foundation, Inc.
+;;  Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 ;; This file is part of GNU CC.
 
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU CC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;- Information about MCF5200 port.
+
+;;- The MCF5200 "ColdFire" architecture is a reduced version of the
+;;- 68k ISA.  Differences include reduced support for byte and word
+;;- operands and the removal of BCD, bitfield, rotate, and integer
+;;- divide instructions.  The TARGET_5200 flag turns the use of the
+;;- removed opcodes and addressing modes off.
+;;- 
 
 
 ;;- instruction definitions
@@ -36,7 +46,7 @@
 ;;- 'd' one of the data registers can be used.
 ;;- 'f' one of the m68881 registers can be used
 ;;- 'r' either a data or an address register can be used.
-;;- 'x' if one of the Sun FPA registers                    
+;;- 'x' if one of the Sun FPA registers
 ;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15).
 
 ;;- Immediate Floating point operator constraints
 ;;- 'J'  -32768 .. 32767
 ;;- '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
 ;;- into play by defining "%$" and "%&" to expand to "s" and "d" rather
 ;;- than "".
 
+;;- Information about 68060 port.
+
+;;- The 68060 executes all 68030 and 68881/2 instructions, but some must
+;;- be emulated in software by the OS.  It is faster to avoid these
+;;- instructions and issue a library call rather than trapping into
+;;- the kernel.  The affected instructions are: divs.l <ea>,Dr:Dq;
+;;- divu.l <ea>,Dr:Dq; muls.l <ea>,Dr:Dq; mulu.l <ea>,Dr:Dq; and
+;;- fscale.  The TARGET_68060 flag turns the use of the opcodes off.
 
 ;;-            FPA port explanation:
 
   return output_move_double (operands);
 }")
 
-(define_insn ""
+(define_insn "pushdi"
   [(set (match_operand:DI 0 "push_operand" "=m")
-       (match_operand:DI 1 "general_operand" "ro<>Fy"))]
+       (match_operand:DI 1 "general_operand" "ro<>Fyi"))]
   ""
   "*
 {
 ;; (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" "oa>,d"))
-   (clobber (match_scratch:SI 1 "=d,d"))
-   (clobber (match_scratch:SI 2 "=d,"))]
+       (match_operand:DI 0 "nonimmediate_operand" "am,d"))
+   (clobber (match_scratch:SI 1 "=X,d"))
+   (clobber (match_scratch:DI 2 "=d,X"))]
   ""
   "*
 {
-  if (GET_CODE (operands[0]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    operands[3] = operands[0];
-  else
-    operands[3] = adj_offsettable_operand (operands[0], 4);
-  if (DATA_REG_P (operands[0]))
-    operands[2] = operands[0];
+  if (which_alternative == 0)
+    {
+      rtx xoperands[2];
+
+      xoperands[0] = operands[2];
+      xoperands[1] = operands[0];
+      output_move_double (xoperands);
+      cc_status.flags |= CC_REVERSED;
+      return \"neg%.l %R2\;negx%.l %2\";
+    }
+  if (find_reg_note (insn, REG_DEAD, operands[0]))
+    {
+      cc_status.flags |= CC_REVERSED;
+      return \"neg%.l %R0\;negx%.l %0\";
+    }
   else
-    output_asm_insn (\"move%.l %0,%2\", operands);
-  /*
-  ** 'sub' clears %1, and also clears the X cc bit
-  ** 'tst' sets the Z cc bit according to the low part of the DImode operand
-  ** 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part
-  */
-  return \"sub%.l %1,%1\;tst%.l %3\;subx%.l %1,%2\";
+    /*
+    ** 'sub' clears %1, and also clears the X cc bit
+    ** 'tst' sets the Z cc bit according to the low part of the DImode operand
+    ** 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part
+    */
+    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"))]
   ""
   /* ISI's assembler fails to handle tstl a0.  */
   if (! ADDRESS_REG_P (operands[0]))
 #else
-  if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
+  if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
 #endif
     return \"tst%.l %0\";
   /* If you think that the 68020 does not support tstl a0,
 
 ;; 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"))]
   ""
   "tst%.b %0")
-  
+
 (define_expand "tstsf"
   [(set (cc0)
        (match_operand:SF 0 "general_operand" ""))]
   "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)
     return \"sub%.l %R2,%R0\;subx%.l %2,%0\";
   else
     {
-      return \"sub%.l %R1,%R0\;subx%.l %1,%0\";
       cc_status.flags |= CC_REVERSED;
+      return \"sub%.l %R1,%R0\;subx%.l %1,%0\";
     }
 }")
 
   ""
   "
 {
-  if (flag_pic && symbolic_operand (operands[1], SImode)) 
+  m68k_last_compare_had_fp_operands = 0;
+  if (flag_pic && symbolic_operand (operands[1], SImode))
     {
-      /* The source is an address which requires PIC relocation.  
+      /* 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 */
     }
 }")
 
-;; 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,>")))]
-  ""
+                (match_operand:SI 1 "general_operand" "mr,rKs,>")))]
+  "!TARGET_5200"
   "*
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
 #endif
 }")
 
-(define_insn "cmphi"
+(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
+  return \"cmp%.l %d1,%d0\";
+#endif
+}")
+
+(define_expand "cmphi"
+  [(set (cc0)
+       (compare (match_operand:HI 0 "nonimmediate_operand" "")
+                (match_operand:HI 1 "general_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,>")))]
-  ""
+  "!TARGET_5200"
   "*
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
 #endif
 }")
 
-(define_insn "cmpqi"
+(define_expand "cmpqi"
+  [(set (cc0)
+       (compare (match_operand:QI 0 "nonimmediate_operand" "")
+                (match_operand:QI 1 "general_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,>")))]
-  ""
+  "!TARGET_5200"
   "*
 {
   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
   "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]));
 ;; Recognizers for btst instructions.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+  [(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" "di"))))]
   "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
                            (const_int 1)
                            (minus:SI (const_int 31)
                                      (match_operand:SI 1 "general_operand" "di"))))]
 ;; are automatically masked to 3 or 5 bits.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
                            (const_int 1)
                            (minus:SI (const_int 7)
                                      (and:SI
   "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
                            (const_int 1)
                            (minus:SI (const_int 31)
                                      (and:SI
 ;; Nonoffsettable mem refs are ok in this one pattern
 ;; since we don't try to adjust them.
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "md")
+  [(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"
 }")
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do")
+  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do")
                            (const_int 1)
                            (match_operand:SI 1 "const_int_operand" "n")))]
   ""
     {
       operands[0] = adj_offsettable_operand (operands[0],
                                             INTVAL (operands[1]) / 8);
-      operands[1] = gen_rtx (CONST_INT, VOIDmode, 
+      operands[1] = gen_rtx (CONST_INT, VOIDmode,
                             7 - INTVAL (operands[1]) % 8);
       return output_btst (operands, operands[1], operands[0], insn, 7);
     }
 
 ;; A special case in which it is not desirable
 ;; to reload the constant into a data register.
-(define_insn ""
+(define_insn "pushexthisi_const"
   [(set (match_operand:SI 0 "push_operand" "=m")
        (match_operand:SI 1 "const_int_operand" "J"))]
   "INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000"
 ;; Special case of fullword move when source is zero.
 ;; The reason this is special is to avoid loading a zero
 ;; into a data reg with moveq in order to store it elsewhere.
-   
-(define_insn ""
+
+(define_insn "movsi_const0"
   [(set (match_operand:SI 0 "general_operand" "=g")
        (const_int 0))]
   ;; clr insns on 68000 read before writing.
-  ;; This isn't so on the 68010, but we have no alternative for it.
-  "(TARGET_68020
+  ;; 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]))
-    return \"sub%.l %0,%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)
+  if (DATA_REG_P (operands[0]) && (!TARGET_68020 && !TARGET_5200))
 #if defined(MOTOROLA) && !defined(CRDS)
     return \"moveq%.l %#0,%0\";
 #else
   return \"clr%.l %0\";
 }")
 
-;; General case of fullword move. 
+;; General case of fullword move.
 ;;
 ;; This is the main "hook" for PIC code.  When generating
 ;; PIC, movsi is responsible for determining when the source address
 ;; to perform the actual relocation.
 ;;
 ;; In both the PIC and non-PIC cases the patterns generated will
-;; matched by the next define_insn. 
+;; matched by the next define_insn.
 (define_expand "movsi"
   [(set (match_operand:SI 0 "general_operand" "")
        (match_operand:SI 1 "general_operand" ""))]
   ""
   "
 {
-  if (flag_pic && symbolic_operand (operands[1], SImode)) 
+  if (flag_pic && symbolic_operand (operands[1], SImode))
     {
-      /* The source is an address which requires PIC relocation.  
+      /* 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 */
   ;; 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"))]
-  ""
+  "!TARGET_5200"
   "*
 {
   if (which_alternative == 3)
-    return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\"; 
+    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)
-    {
-      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 alternative for it.  */
-         && (TARGET_68020
-             || !(GET_CODE (operands[0]) == MEM
-                  && MEM_VOLATILE_P (operands[0]))))
-       return \"clr%.l %0\";
-      else if (DATA_REG_P (operands[0]))
-       return output_move_const_into_data_reg (operands);
-      else if (ADDRESS_REG_P (operands[0])
-              && INTVAL (operands[1]) < 0x8000
-              && INTVAL (operands[1]) >= -0x8000)
-       return \"move%.w %1,%0\";
-      else if (push_operand (operands[0], SImode)
-              && INTVAL (operands[1]) < 0x8000
-              && INTVAL (operands[1]) >= -0x8000)
-        return \"pea %a1\";
-    }
-  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"
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r<>,g")
+       (match_operand:SI 1 "general_operand" "g,r<>"))]
+  "TARGET_5200"
+  "* return output_move_simode (operands);")
+
+(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_operand" "g"))]
-  ""
-  "*
-{
-  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 alternative for it.  */
-         && (TARGET_68020
-             || !(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\";
-}")
+  "!TARGET_5200"
+  "* return output_move_himode (operands);")
+
+ (define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=r<>,g")
+       (match_operand:HI 1 "general_operand" "g,r<>"))]
+  "TARGET_5200"
+  "* return output_move_himode (operands);")
 
 (define_insn "movstricthi"
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
   ""
   "*
 {
-  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 alternative for it.  */
-         && (TARGET_68020
-             || !(GET_CODE (operands[0]) == MEM
-                  && MEM_VOLATILE_P (operands[0]))))
-       return \"clr%.w %0\";
-    }
+  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%.w %0\";
   return \"move%.w %1,%0\";
 }")
 
-(define_insn "movqi"
-  [(set (match_operand:QI 0 "general_operand" "=d,*a,m,m,?*a")
-       (match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi,?*a,m"))]
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "general_operand" "")
+       (match_operand:QI 1 "general_operand" ""))]
   ""
-  "*
-{
-  rtx xoperands[4];
-
-  /* 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 \"\";
-    }
-
-  /* Moving a byte into an address register is not possible.  */
-  /* Use d0 as an intermediate, but don't clobber its contents.  */
-  if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
-    {
-      /* ??? For 2.5, don't allow this choice and use secondary reloads
-        instead.
-
-        See if the address register is used in the address.  If it
-        is, we have to generate a more complex sequence than those below.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands[1], NULL_RTX))
-       {
-         /* See if the stack pointer is used in the address.  If it isn't,
-            we can push d0 or d1 (the insn can't use both of them) on
-            the stack, perform our move into d0/d1, copy the byte from d0/1,
-            and pop d0/1.  */
-         if (! reg_mentioned_p (stack_pointer_rtx, operands[1]))
-           {
-             if (! refers_to_regno_p (0, 1, operands[1], NULL_RTX))
-               return \"move%.l %/d0,%-\;move%.b %1,%/d0\;move%.l %/d0,%0\;move%.l %+,%/d0\";
-             else
-               return \"move%.l %/d1,%-\;move%.b %1,%/d1\;move%.l %/d1,%0\;move%.l %+,%/d1\";
-           }
-         else
-           {
-             /* Otherwise, we know that d0 cannot be used in the address
-                (since sp and one address register is).  Assume that sp is
-                being used as a base register and replace the address
-                register that is our operand[0] with d0.  */
-             rtx reg_map[FIRST_PSEUDO_REGISTER];
-             int i;
-
-             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-               reg_map[i] = 0;
-
-             reg_map[REGNO (operands[0])] = gen_rtx (REG, Pmode, 0);
-             operands[1] = copy_rtx (operands[1]);
-             replace_regs (operands[1], reg_map, FIRST_PSEUDO_REGISTER, 0);
-             return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\";
-           }
-       }
-
-      /* If the address of operand 1 uses d0, choose d1 as intermediate.  */
-      if (refers_to_regno_p (0, 1, operands[1], NULL_RTX))
-       return \"exg %/d1,%0\;move%.b %1,%/d1\;exg %/d1,%0\";
-      /* Otherwise d0 is usable.
-        (An effective address on the 68k can't use two d-regs.)  */
-      else
-       return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\";
-    }
-    
-  /* Likewise for moving from an address reg.  */
-  if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
-    {
-      /* ??? For 2.5, don't allow this choice and use secondary reloads
-        instead.
-
-        See if the address register is used in the address.  If it
-        is, we have to generate a more complex sequence than those below.  */
-      if (refers_to_regno_p (REGNO (operands[1]), REGNO (operands[1]) + 1,
-                            operands[0], NULL_RTX))
-       {
-         /* See if the stack pointer is used in the address.  If it isn't,
-            we can push d0 or d1 (the insn can't use both of them) on
-            the stack, copy the byte to d0/1, perform our move from d0/d1, 
-            and pop d0/1.  */
-         if (! reg_mentioned_p (stack_pointer_rtx, operands[0]))
-           {
-             if (! refers_to_regno_p (0, 1, operands[0], NULL_RTX))
-               return \"move%.l %/d0,%-\;move%.l %1,%/d0\;move%.b %/d0,%0\;move%.l %+,%/d0\";
-             else
-               return \"move%.l %/d1,%-\;move%.l %1,%/d1\;move%.b %/d1,%0\;move%.l %+,%/d1\";
-           }
-         else
-           {
-             /* Otherwise, we know that d0 cannot be used in the address
-                (since sp and one address register is).  Assume that sp is
-                being used as a base register and replace the address
-                register that is our operand[1] with d0.  */
-             rtx reg_map[FIRST_PSEUDO_REGISTER];
-             int i;
-
-             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-               reg_map[i] = 0;
-
-             reg_map[REGNO (operands[1])] = gen_rtx (REG, Pmode, 0);
-             operands[0] = copy_rtx (operands[0]);
-             replace_regs (operands[0], reg_map, FIRST_PSEUDO_REGISTER, 0);
-             return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\";
-           }
-       }
+  "")
 
-      if (refers_to_regno_p (0, 1, operands[0], NULL_RTX))
-        return \"exg %/d1,%1\;move%.b %/d1,%0\;exg %/d1,%1\";
-      else
-        return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\";
-    }
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
+       (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))]
+  "!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 alternative for it.  */
-  if (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]) == -1)
-       {
-         CC_STATUS_INIT;
-         return \"st %0\";
-       }
-    }
-  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_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=d*a<>,d*am")
+       (match_operand:QI 1 "general_operand" "d*ami,d*a<>"))]
+  "TARGET_5200"
+  "* return output_move_qimode (operands);")
 
 (define_insn "movstrictqi"
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
 {
   if (operands[1] == const0_rtx
       /* clr insns on 68000 read before writing.
-         This isn't so on the 68010, but we have no alternative for it.  */
-      && (TARGET_68020
+         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_expand "movsf"
+  [(set (match_operand:SF 0 "general_operand" "")
+       (match_operand:SF 1 "general_operand" ""))]
+  ""
+  "")
+
+(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 \"move%.l %1,%0\";
 }")
 
-(define_insn "movdf"
+(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)
         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" "")
 (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]))
 }
 ")
 
+(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)
         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)
 
 ;; this is the canonical form for (lshiftrt:DI x 32)
 (define_insn "zero_extendsidi2"
-  [(set (match_operand:DI 0 "general_operand" "ro,<,>")
-    (zero_extend:DI (match_operand:SI 1 "general_operand" "rm,rm,rm")))]
+  [(set (match_operand:DI 0 "general_operand" "rm")
+    (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
   ""
   "*
 {
   CC_STATUS_INIT;
-  if (which_alternative == 2)
-    return \"clr%.l %0\;move%.l %1,%0\";
-  if (which_alternative == 1)
-    return \"move%.l %1,%0\;clr%.l %0\";
   if (GET_CODE (operands[0]) == REG)
     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 (ADDRESS_REG_P (operands[0]))
 {
   CC_STATUS_INIT;
   operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  if (TARGET_68020)
+  if (TARGET_68020 || TARGET_5200)
     return \"move%.b %1,%2\;extb%.l %2\;smi %0\;extb%.l %0\";
   else
-    return \"move%.b %1,%2\;ext%.w %0\;ext%.l %2\;smi %0\;ext%.w %0\;ext%.l %0\";
+    return \"move%.b %1,%2\;ext%.w %0\;ext%.l %2\;move%.l %2,%0\;smi %0\";
 }")
 
 (define_insn "extendhidi2"
 {
   CC_STATUS_INIT;
   operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  if (TARGET_68020)
+  if (TARGET_68020 || TARGET_5200)
     return \"move%.w %1,%2\;ext%.l %2\;smi %0\;extb%.l %0\";
   else
     return \"move%.w %1,%2\;ext%.l %2\;smi %0\;ext%.w %0\;ext%.l %0\";
 {
   CC_STATUS_INIT;
   operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  if (TARGET_68020)
+  if (TARGET_68020 || TARGET_5200)
     return \"move%.l %1,%2\;smi %0\;extb%.l %0\";
   else
     return \"move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0\";
       operands[1] = operands[2];
       operands[2] = tmp;
     }
-  if (TARGET_68020)
-    return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;extb%.l %0\";
+  if (GET_CODE (operands[1]) == REG
+      && REGNO (operands[1]) == REGNO (operands[3]))
+    output_asm_insn (\"add%.l %2,%3\", operands);
+  else
+    output_asm_insn (\"move%.l %2,%3\;add%.l %1,%3\", operands);
+  if (TARGET_68020 || TARGET_5200)
+    return \"smi %0\;extb%.l %0\";
   else
-    return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;ext%.w %0\;ext%.l %0\";
+    return \"smi %0\;ext%.w %0\;ext%.l %0\";
 }")
 
 (define_insn "extendhisi2"
 (define_insn "extendqisi2"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
-  "TARGET_68020"
+  "TARGET_68020 || TARGET_5200"
   "extb%.l %0")
 \f
 ;; Conversions between float and double.
 \f
 ;; add instructions
 
-(define_insn "adddia_sexthishl32"
-  [(set (match_operand:DI 0 "register_operand" "+a")
-    (plus:DI (ashift:DI (sign_extend:DI
-          (match_operand:HI 1 "general_operand" "rm"))
-            (const_int 32))
-        (match_dup 0)))]
+(define_insn "adddi_lshrdi_63"
+  [(set (match_operand:DI 0 "general_operand" "=d")
+    (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "rm")
+            (const_int 63))
+        (match_dup 1)))
+   (clobber (match_scratch:SI 2 "=d"))]
   ""
   "*
 {
-  CC_STATUS_INIT;
-  return \"add%.w %1,%0\";
-} ")
-
-(define_insn "adddid_sexthishl32"
-  [(set (match_operand:DI 0 "general_operand" "+ro")
-    (plus:DI (ashift:DI (sign_extend:DI
-          (match_operand:HI 1 "general_operand" "rm"))
+  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);
+  else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC
+        || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+    operands[4] = operands[1];
+  else
+    operands[4] = adj_offsettable_operand (operands[1], 4);
+  if (GET_CODE (operands[1]) == MEM
+   && GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+    output_asm_insn (\"move%.l %4,%3\", operands);
+  output_asm_insn (\"move%.l %1,%0\;smi %2\", operands);
+  if (TARGET_68020 || TARGET_5200)
+    output_asm_insn (\"extb%.l %2\", operands);
+  else
+    output_asm_insn (\"ext%.w %2\;ext%.l %2\", operands);
+  if (GET_CODE (operands[1]) != MEM
+   || GET_CODE (XEXP (operands[1], 0)) != PRE_DEC)
+    output_asm_insn (\"move%.l %4,%3\", operands);
+  return \"sub%.l %2,%3\;subx%.l %2,%0\";
+}")
+
+(define_insn "adddi_sexthishl32"
+  [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+    (plus:DI (ashift:DI (sign_extend:DI
+          (match_operand:HI 1 "general_operand" "rm,rm,rm,rm"))
             (const_int 32))
-        (match_dup 0)))
-   (clobber (match_scratch:SI 2 "=a"))]
-  ""
+        (match_operand:DI 2 "general_operand" "0,0,0,0")))
+   (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
-  return \"move%.w %1,%2\;add%.l %2,%0\";
+  if (ADDRESS_REG_P (operands[0]))
+    return \"add%.w %1,%0\";
+  else if (ADDRESS_REG_P (operands[3]))
+    return \"move%.w %1,%3\;add%.l %3,%0\";
+  else
+    return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%0\";
 } ")
 
 (define_insn "adddi_dilshr32"
   return \"add%.l %1,%0\";
 } ")
 
-(define_insn "adddi_mem"
-  [(set (match_operand:DI 0 "general_operand" "=o,<,>")
-       (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0")
-                (match_operand:DI 2 "general_operand" "d,d,d")))
-   (clobber (match_scratch:SI 3 "=d,d,d"))]
+(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")))
+   (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
   ""
   "*
 {
-  CC_STATUS_INIT;
-  operands[4] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
-  if (which_alternative == 2)
+  if (DATA_REG_P (operands[0]))
     {
-      operands[1] = gen_rtx (MEM, SImode,
-              gen_rtx (PLUS, VOIDmode, XEXP(operands[0], 0),
-                       gen_rtx (CONST_INT, VOIDmode, -8)));
-      return \"move%.l %0,%3\;add%.l %4,%0\;addx%.l %2,%3\;move%.l %3,%1\";
+      if (DATA_REG_P (operands[2]))
+       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\";
+       }
+      else
+       {
+         /* TODO : this should work also for CONST operands[2] */
+         if (GET_CODE (operands[2]) == REG)
+           operands[1] = gen_rtx (REG, SImode, REGNO (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\";
+       }
     }
-  if (which_alternative == 1)
-    {
-      operands[1] = XEXP(operands[0], 0);
-      return \"add%.l %4,%0\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%1\";
-    }
-  operands[1] = adj_offsettable_operand (operands[0], 4);
-  return \"add%.l %4,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0\";
-} ")
-
-(define_insn "adddi3"
-  [(set (match_operand:DI 0 "general_operand" "=d,d,d,<")
-       (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
-                (match_operand:DI 2 "general_operand" "*ao,>,d,<")))]
-  ""
-  "*
-{
-  if (which_alternative == 3)
-    return \"add%.l %2,%0\;addx%.l %2,%0\";
-  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  if (which_alternative == 1)
+  else if (GET_CODE (operands[0]) == MEM)
     {
+      if (GET_CODE (operands[2]) == MEM
+         && GET_CODE (XEXP (operands[2], 0)) == PRE_DEC)
+       return \"add%.l %2,%0\;addx%.l %2,%0\";
       CC_STATUS_INIT;
-      return \"add%.l %2,%0\;add%.l %2,%1\;negx%.l %0\;neg%.l %0\";
+      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)));
+         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)
+       {
+         operands[1] = XEXP(operands[0], 0);
+         return \"add%.l %R2,%0\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%1\";
+       }
+      else
+       {
+         operands[1] = adj_offsettable_operand (operands[0], 4);
+         return \"add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0\";
+       }
     }
-  if (GET_CODE (operands[2]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
-  else
-    operands[3] = adj_offsettable_operand (operands[2], 4);
-  if (which_alternative == 2)
-    return \"add%.l %3,%1\;addx%.l %2,%0\";
-  CC_STATUS_INIT;
-  /* negx + neg simulates (non-existent) addx #0 */
-  /* TODO : this should work also for CONST operands[2] */
-  return \"add%.l %3,%1\;negx%.l %0\;neg%.l %0\;add%.l %2,%0\";
 } ")
 
 (define_insn "addsi_lshrsi_31"
   return \"\";
 }")
 
+(define_expand "addsi3"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (plus:SI (match_operand:SI 1 "general_operand" "")
+                (match_operand:SI 2 "general_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"
+(define_insn "*addsi3_internal"
   [(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;
-       }
+  "! TARGET_5200"
+  "* return output_addsi3 (operands);")
 
-      /* 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 (ADDRESS_REG_P (operands[0])
-               ? \"addq%.w %2,%0\"
-               : \"addq%.l %2,%0\");
-      if (INTVAL (operands[2]) < 0
-         && INTVAL (operands[2]) >= -8)
-        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                                - INTVAL (operands[2]));
-         return (ADDRESS_REG_P (operands[0])
-                 ? \"subq%.w %2,%0\"
-                 : \"subq%.l %2,%0\");
-       }
-      /* On everything except the 68000 it is faster to use two
-        addqw instructions to add a small integer (8 < N <= 16)
-        to an address register.  Likewise for subqw.*/
-      if (INTVAL (operands[2]) > 8
-         && INTVAL (operands[2]) <= 16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
-       {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
-         return \"addq%.w %#8,%0\;addq%.w %2,%0\";
-       }
-      if (INTVAL (operands[2]) < -8
-         && INTVAL (operands[2]) >= -16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
-       {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, 
-                                 - INTVAL (operands[2]) - 8);
-         return \"subq%.w %#8,%0\;subq%.w %2,%0\";
-       }
-#endif
-      if (ADDRESS_REG_P (operands[0])
-         && INTVAL (operands[2]) >= -0x8000
-         && INTVAL (operands[2]) < 0x8000)
-       return \"add%.w %2,%0\";
-    }
-  return \"add%.l %2,%0\";
-}")
+(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_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"))))]
-  ""
+  "!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")))]
-  ""
+  "!TARGET_5200"
   "*
 {
-#ifndef NO_ADDSUB_Q
   if (GET_CODE (operands[2]) == CONST_INT)
     {
+#ifndef NO_ADDSUB_Q
       /* If the constant would be a negative number when interpreted as
         HImode, make it negative.  This is usually, but not always, done
         elsewhere in the compiler.  First check for constants out of range,
                                 - INTVAL (operands[2]));
          return \"subq%.w %2,%0\";
        }
-      /* On everything except the 68000 it is faster to use two
-        addqw instructions to add a small integer (8 < N <= 16)
-        to an address register.  Likewise for subqw. */
-      if (INTVAL (operands[2]) > 8
-         && INTVAL (operands[2]) <= 16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
-       {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
-         return \"addq%.w %#8,%0\;addq%.w %2,%0\";
-       }
-      if (INTVAL (operands[2]) < -8
-         && INTVAL (operands[2]) >= -16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+      /* On the CPU32 it is faster to use two addqw instructions to
+        add a small integer (8 < N <= 16) to a register.  
+        Likewise for subqw. */
+      if (TARGET_CPU32 && REG_P (operands[0]))
        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, 
-                                - INTVAL (operands[2]) - 8);
-         return \"subq%.w %#8,%0\;subq%.w %2,%0\";
+         if (INTVAL (operands[2]) > 8
+             && INTVAL (operands[2]) <= 16)
+           {
+             operands[2] = gen_rtx (CONST_INT, VOIDmode, 
+                                    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);
+             return \"subq%.w %#8,%0\;subq%.w %2,%0\";
+           }
        }
-    }
 #endif
+      if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA  
+           return \"lea (%c2,%0),%0\";
+#else
+           return \"lea %0@(%c2),%0\";
+#endif
+    }
   return \"add%.w %2,%0\";
 }")
 
   [(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")))]
-  ""
+  "!TARGET_5200"
   "*
 {
-#ifndef NO_ADDSUB_Q
   if (GET_CODE (operands[1]) == CONST_INT)
     {
+#ifndef NO_ADDSUB_Q
       /* If the constant would be a negative number when interpreted as
         HImode, make it negative.  This is usually, but not always, done
         elsewhere in the compiler.  First check for constants out of range,
                                 - INTVAL (operands[1]));
          return \"subq%.w %1,%0\";
        }
-      /* On everything except the 68000 it is faster to use two
-        addqw instructions to add a small integer (8 < N <= 16)
-        to an address register.  Likewise for subqw. */
-      if (INTVAL (operands[1]) > 8
-         && INTVAL (operands[1]) <= 16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+      /* On the CPU32 it is faster to use two addqw instructions to
+        add a small integer (8 < N <= 16) to a register. 
+        Likewise for subqw. */
+      if (TARGET_CPU32 && REG_P (operands[0]))
        {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
-         return \"addq%.w %#8,%0\;addq%.w %1,%0\";
-       }
-      if (INTVAL (operands[1]) < -8
-         && INTVAL (operands[1]) >= -16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
-       {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, 
-                                - INTVAL (operands[1]) - 8);
-         return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+         if (INTVAL (operands[1]) > 8
+             && INTVAL (operands[1]) <= 16)
+           {
+             operands[1] = gen_rtx (CONST_INT, VOIDmode, 
+                                    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);
+             return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+           }
        }
-    }
 #endif
+      if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA  
+           return \"lea (%c1,%0),%0\";
+#else
+           return \"lea %0@(%c1),%0\";
+#endif
+    }
   return \"add%.w %1,%0\";
 }")
 
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
                 (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "*
 {
-#ifndef NO_ADDSUB_Q
   if (GET_CODE (operands[1]) == CONST_INT)
     {
+#ifndef NO_ADDSUB_Q
       /* If the constant would be a negative number when interpreted as
         HImode, make it negative.  This is usually, but not always, done
         elsewhere in the compiler.  First check for constants out of range,
                                 - INTVAL (operands[1]));
          return \"subq%.w %1,%0\";
        }
-      /* On everything except the 68000 it is faster to use two
-        addqw instructions to add a small integer (8 < N <= 16)
-        to an address register.  Likewise for subqw. */
-      if (INTVAL (operands[1]) > 8
-         && INTVAL (operands[1]) <= 16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
-       {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
-         return \"addq%.w %#8,%0\;addq%.w %1,%0\";
-       }
-      if (INTVAL (operands[1]) < -8
-         && INTVAL (operands[1]) >= -16
-         && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+      /* On the CPU32 it is faster to use two addqw instructions to
+        add a small integer (8 < N <= 16) to a register.
+        Likewise for subqw. */
+      if (TARGET_CPU32 && REG_P (operands[0])) 
        {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, 
-                                - INTVAL (operands[1]) - 8);
-         return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+         if (INTVAL (operands[1]) > 8
+             && INTVAL (operands[1]) <= 16)
+           {
+             operands[1] = gen_rtx (CONST_INT, VOIDmode, 
+                                    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);
+             return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+           }
        }
-    }
 #endif
+      if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA  
+           return \"lea (%c1,%0),%0\";
+#else
+           return \"lea %0@(%c1),%0\";
+#endif
+    }
   return \"add%.w %1,%0\";
 }")
 
   [(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")))]
-  ""
+  "!TARGET_5200"
   "*
 {
 #ifndef NO_ADDSUB_Q
   [(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")))]
-  ""
+  "!TARGET_5200"
   "*
 {
 #ifndef NO_ADDSUB_Q
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
                 (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "*
 {
 #ifndef NO_ADDSUB_Q
 \f
 ;; subtract instructions
 
-(define_insn "subdia_sexthishl32"
-  [(set (match_operand:DI 0 "register_operand" "+a")
-    (minus:DI (match_dup 0)
-        (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm"))
-            (const_int 32))))]
-  ""
-  "*
-{
-  CC_STATUS_INIT;
-  return \"sub%.w %1,%0\";
-} ")
-
-(define_insn "subdid_sexthishl32"
-  [(set (match_operand:DI 0 "general_operand" "+ro")
-    (minus:DI (match_dup 0)
-        (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm"))
+(define_insn "subdi_sexthishl32"
+  [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+    (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
+        (ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm,rm"))
             (const_int 32))))
-   (clobber (match_scratch:SI 2 "=a"))]
-  ""
+   (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
-  return \"move%.w %1,%2\;sub%.l %2,%0\";
+  if (ADDRESS_REG_P (operands[0]))
+    return \"sub%.w %2,%0\";
+  else if (ADDRESS_REG_P (operands[3]))
+    return \"move%.w %2,%3\;sub%.l %3,%0\";
+  else
+    return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%0\";
 } ")
 
 (define_insn "subdi_dishl32"
   return \"sub%.l %1,%0\";
 } ")
 
-(define_insn "subdi_mem"
-  [(set (match_operand:DI 0 "general_operand" "=o,<,>")
-       (minus:DI (match_operand:DI 1 "general_operand" "0,0,0")
-                (match_operand:DI 2 "register_operand" "d,d,d")))
-   (clobber (match_scratch:SI 3 "=d,d,d"))]
+(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")))
+   (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
   ""
   "*
 {
-  CC_STATUS_INIT;
-  operands[4] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
-  if (which_alternative == 2)
-    {
-      operands[1] = gen_rtx (MEM, SImode,
-              gen_rtx (PLUS, VOIDmode, XEXP(operands[0], 0),
-                       gen_rtx (CONST_INT, VOIDmode, -8)));
-      return \"move%.l %0,%3\;sub%.l %4,%0\;subx%.l %2,%3\;move%.l %3,%1\";
-    }
-  if (which_alternative == 1)
+  if (DATA_REG_P (operands[0]))
     {
-      operands[1] = XEXP(operands[0], 0);
-      return \"sub%.l %4,%0\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%1\";
+      if (DATA_REG_P (operands[2]))
+       return \"sub%.l %R2,%R0\;subx%.l %2,%0\";
+      else if (GET_CODE (operands[2]) == MEM
+         && GET_CODE (XEXP (operands[2], 0)) == POST_INC)
+       {
+         return \"move%.l %2,%3\;sub%.l %2,%R0\;subx%.l %3,%0\";
+       }
+      else
+       {
+         /* TODO : this should work also for CONST operands[2] */
+         if (GET_CODE (operands[2]) == REG)
+           operands[1] = gen_rtx (REG, SImode, REGNO (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\";
+       }
     }
-  operands[1] = adj_offsettable_operand (operands[0], 4);
-  return \"sub%.l %4,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0\";
-} ")
-
-(define_insn "subdi3"
-  [(set (match_operand:DI 0 "general_operand" "=d,d,d,<")
-       (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
-                (match_operand:DI 2 "general_operand" "*ao,>,d,<")))]
-  ""
-  "*
-{
-  if (which_alternative == 3)
-    return \"sub%.l %2,%0\;subx%.l %2,%0\";
-  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  if (which_alternative == 1)
+  else if (GET_CODE (operands[0]) == MEM)
     {
+      if (GET_CODE (operands[2]) == MEM
+         && GET_CODE (XEXP (operands[2], 0)) == PRE_DEC)
+       return \"sub%.l %2,%0\;subx%.l %2,%0\";
       CC_STATUS_INIT;
-      return \"neg%.l %0\;add%.l %2,%0\;sub%.l %2,%1\;negx%.l %0\";
+      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)));
+         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)
+       {
+         operands[1] = XEXP(operands[0], 0);
+         return \"sub%.l %R2,%0\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%1\";
+       }
+      else
+       {
+         operands[1] = adj_offsettable_operand (operands[0], 4);
+         return \"sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0\";
+       }
     }
-  if (GET_CODE (operands[2]) == REG)
-    operands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
-  else
-    operands[3] = adj_offsettable_operand (operands[2], 4);
-  if (which_alternative == 2)
-    return \"sub%.l %3,%1\;subx%.l %2,%0\";
-  CC_STATUS_INIT;
-  /* neg + negx simulates (non-existent) subx #0 */
-  /* TODO : this should work also for CONST operands[2] */
-  return \"neg%.l %0\;sub%.l %3,%1\;negx%.l %0\;sub%.l %2,%0\";
 } ")
 
 (define_insn "subsi3"
        (minus:SI (match_operand:SI 1 "general_operand" "0")
                  (sign_extend:SI
                   (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
-  ""
+  "!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")))]
-  ""
+  "!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")))]
-  ""
+  "!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")))]
-  ""
+  "!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")))]
-  ""
+  "!TARGET_5200"
   "sub%.b %1,%0")
 
 (define_expand "subdf3"
 #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"
   "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<>")))]
+  "TARGET_5200"
+  "muls%.l %2,%0")
+
 (define_insn "umulhisi3"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (mult:SI (zero_extend:SI
          (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
                                             (zero_extend:DI (match_dup 2)))
                                    (const_int 32))))])]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "")
 
 (define_insn ""
        (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
                                           (zero_extend:DI (match_dup 2)))
                                  (const_int 32))))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "mulu%.l %2,%3:%0")
 
 ; Match immediate case.  For 2.4 only match things < 2^31.
        (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
                                           (match_dup 2))
                                  (const_int 32))))]
-  "TARGET_68020
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200
    && (unsigned) INTVAL (operands[2]) <= 0x7fffffff"
   "mulu%.l %2,%3:%0")
 
          (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
                                             (sign_extend:DI (match_dup 2)))
                                    (const_int 32))))])]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "")
 
 (define_insn ""
        (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
                                           (sign_extend:DI (match_dup 2)))
                                  (const_int 32))))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "muls%.l %2,%3:%0")
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=d")
        (mult:SI (match_operand:SI 1 "register_operand" "%0")
-                (match_operand:SI 2 "const_int_operand" "n")))
+                (match_operand:SI 2 "const_sint32_operand" "")))
    (set (match_operand:SI 3 "register_operand" "=d")
        (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
                                           (match_dup 2))
                                  (const_int 32))))]
-  "TARGET_68020
-   /* This test is a noop on 32 bit machines,
-      but important for a cross-compiler hosted on 64-bit machines.  */
-   && INTVAL (operands[2]) <= 0x7fffffff
-   && INTVAL (operands[2]) >= -0x80000000"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "muls%.l %2,%3:%0")
 
 (define_expand "umulsi3_highpart"
                     (zero_extend:DI (match_operand:SI 2 "general_operand" "")))
            (const_int 32))))
      (clobber (match_dup 3))])]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "
 {
   operands[3] = gen_reg_rtx (SImode);
                   (zero_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm")))
          (const_int 32))))
    (clobber (match_operand:SI 1 "register_operand" "=d"))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "mulu%.l %3,%0:%1")
 
 (define_insn "const_umulsi3_highpart"
                   (match_operand 3 "const_uint32_operand" ""))
          (const_int 32))))
    (clobber (match_operand:SI 1 "register_operand" "=d"))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "mulu%.l %3,%0:%1")
 
 (define_expand "smulsi3_highpart"
                     (sign_extend:DI (match_operand:SI 2 "general_operand" "")))
            (const_int 32))))
      (clobber (match_dup 3))])]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "
 {
   operands[3] = gen_reg_rtx (SImode);
                   (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm")))
          (const_int 32))))
    (clobber (match_operand:SI 1 "register_operand" "=d"))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "muls%.l %3,%0:%1")
 
 (define_insn "const_smulsi3_highpart"
                   (match_operand 3 "const_sint32_operand" ""))
          (const_int 32))))
    (clobber (match_operand:SI 1 "register_operand" "=d"))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
   "muls%.l %3,%0:%1")
 
 (define_expand "muldf3"
   "*
 {
   if (GET_CODE (operands[2]) == CONST_DOUBLE
-      && floating_exact_log2 (operands[2]) && !TARGET_68040)
+      && floating_exact_log2 (operands[2]) && !TARGET_68040 && !TARGET_68060)
     {
       int i = floating_exact_log2 (operands[2]);
       operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
                (match_operand:SI 2 "general_operand" "dmsK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (mod:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_5200"
   "*
 {
   if (find_reg_note (insn, REG_UNUSED, operands[3]))
                 (match_operand:SI 2 "general_operand" "dmsK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (umod:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_68020"
+  "TARGET_68020 && !TARGET_5200"
   "*
 {
   if (find_reg_note (insn, REG_UNUSED, operands[3]))
                (match_operand:HI 2 "general_operand" "dmsK")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (mod:HI (match_dup 1) (match_dup 2)))]
-  ""
+  "!TARGET_5200"
   "*
 {
 #ifdef MOTOROLA
                 (match_operand:HI 2 "general_operand" "dmsK")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (umod:HI (match_dup 1) (match_dup 2)))]
-  ""
+  "!TARGET_5200"
   "*
 {
 #ifdef MOTOROLA
 ;; 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_insn "andsi3"
+
+(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,dmKs")))]
+               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
   ""
+  "")
+
+(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")))]
+  "!TARGET_5200"
   "*
 {
   int logval;
       && (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,
       && (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);
   return \"and%.l %2,%0\";
 }")
 
+(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")))]
+  "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")))]
-  ""
+  "!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")))]
-  ""
+  "!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")
                (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")))]
-  ""
+  "!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")))]
-  ""
+  "!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")
                (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "and%.b %1,%0")
 \f
 ;; inclusive-or instructions
 
-(define_insn "iorsi3"
+(define_expand "iorsi3"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (ior:SI (match_operand:SI 1 "general_operand" "")
+               (match_operand:SI 2 "general_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,dmKs")))]
-  ""
+               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+  "!TARGET_5200"
   "*
 {
   register int logval;
       && 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.  */
       && (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);
   return \"or%.l %2,%0\";
 }")
 
+(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")))]
+  "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")))]
-  ""
+  "!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")))]
-  ""
+  "!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")
                (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")))]
-  ""
+  "!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")))]
-  ""
+  "!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")
                (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "or%.b %1,%0")
 
+;; On all 68k models, this makes faster code in a special case.
+;; 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")
+            (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);
+    }
+  return \"swap %0\;mov%.w %1,%0\";
+}")
+
 (define_insn ""
   [(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")))]
-  ""
+  "!TARGET_5200"
   "*
 {
   int byte_mode;
 \f
 ;; xor instructions
 
-(define_insn "xorsi3"
+(define_expand "xorsi3"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (xor:SI (match_operand:SI 1 "general_operand" "")
+               (match_operand:SI 2 "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")))]
-  ""
+  "!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.  */
   return \"eor%.l %2,%0\";
 }")
 
+(define_insn "xorsi3_5200"
+  [(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")
+
 (define_insn "xorhi3"
   [(set (match_operand:HI 0 "general_operand" "=dm")
        (xor:HI (match_operand:HI 1 "general_operand" "%0")
                (match_operand:HI 2 "general_operand" "dn")))]
-  ""
+  "!TARGET_5200"
   "eor%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
        (xor:HI (match_dup 0)
                (match_operand:HI 1 "general_operand" "dn")))]
-  ""
+  "!TARGET_5200"
   "eor%.w %1,%0")
 
-
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
        (xor:HI (match_operand:HI 1 "general_operand" "dn")
                (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "eor%.w %1,%0")
 
 (define_insn "xorqi3"
   [(set (match_operand:QI 0 "general_operand" "=dm")
        (xor:QI (match_operand:QI 1 "general_operand" "%0")
                (match_operand:QI 2 "general_operand" "dn")))]
-  ""
+  "!TARGET_5200"
   "eor%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
        (xor:QI (match_dup 0)
                (match_operand:QI 1 "general_operand" "dn")))]
-  ""
+  "!TARGET_5200"
   "eor%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
        (xor:QI (match_operand:QI 1 "general_operand" "dn")
                (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "eor%.b %1,%0")
 \f
 ;; negation instructions
 
-(define_insn "negdi2"
-  [(set (match_operand:DI 0 "general_operand" "=d*ao,<")
-       (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
+(define_expand "negdi2"
+  [(set (match_operand:DI 0 "general_operand" "")
+       (neg:DI (match_operand:DI 1 "general_operand" "")))]
   ""
+  "
+{
+  if (TARGET_5200)
+    emit_insn (gen_negdi2_5200 (operands[0], operands[1]));
+  else
+    emit_insn (gen_negdi2_internal (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "negdi2_internal"
+  [(set (match_operand:DI 0 "general_operand" "=<,do,!*a")
+       (neg:DI (match_operand:DI 1 "general_operand" "0,0,0")))]
+  "!TARGET_5200"
   "*
 {
-  if (which_alternative == 1)
+  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);
     return \"neg%.l %1\;negx%.l %0\";
 } ")
 
-(define_insn "negsi2"
+(define_insn "negdi2_5200"
+  [(set (match_operand:DI 0 "general_operand" "=d")
+       (neg:DI (match_operand:DI 1 "general_operand" "0")))]
+  "TARGET_5200"
+  "*
+{
+  operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  return \"neg%.l %1\;negx%.l %0\";
+} ")
+
+(define_expand "negsi2"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (neg:SI (match_operand:SI 1 "general_operand" "")))]
+  ""
+  "
+{
+  if (TARGET_5200)
+    emit_insn (gen_negsi2_5200 (operands[0], operands[1]));
+  else
+    emit_insn (gen_negsi2_internal (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "negsi2_internal"
   [(set (match_operand:SI 0 "general_operand" "=dm")
        (neg:SI (match_operand:SI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
+  "neg%.l %0")
+
+(define_insn "negsi2_5200"
+  [(set (match_operand:SI 0 "general_operand" "=d")
+       (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+  "TARGET_5200"
   "neg%.l %0")
 
 (define_insn "neghi2"
   [(set (match_operand:HI 0 "general_operand" "=dm")
        (neg:HI (match_operand:HI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
   "neg%.w %0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
        (neg:HI (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "neg%.w %0")
 
 (define_insn "negqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm")
        (neg:QI (match_operand:QI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
   "neg%.b %0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
        (neg:QI (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "neg%.b %0")
 
 ;; If using software floating point, just flip the sign bit.
 
       if (result != target)
        emit_move_insn (result, target);
-  
+
       emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
                      operand_subword_force (operands[1], 1, DFmode));
 
 
       if (result != target)
        emit_move_insn (result, target);
-  
+
       emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
                      operand_subword_force (operands[1], 1, DFmode));
 
 (define_insn "one_cmpldi2"
   [(set (match_operand:DI 0 "general_operand" "=dm")
        (not:DI (match_operand:DI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[2] = 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];
   return \"not%.l %1\;not%.l %0\";
 }")
 
-(define_insn "one_cmplsi2"
+(define_expand "one_cmplsi2"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (not:SI (match_operand:SI 1 "general_operand" "")))]
+  ""
+  "
+{
+  if (TARGET_5200)
+    emit_insn (gen_one_cmplsi2_5200 (operands[0], operands[1]));
+  else
+    emit_insn (gen_one_cmplsi2_internal (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "one_cmplsi2_internal"
   [(set (match_operand:SI 0 "general_operand" "=dm")
        (not:SI (match_operand:SI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
+  "not%.l %0")
+
+(define_insn "one_cmplsi2_5200"
+  [(set (match_operand:SI 0 "general_operand" "=d")
+       (not:SI (match_operand:SI 1 "general_operand" "0")))]
+  "TARGET_5200"
   "not%.l %0")
 
 (define_insn "one_cmplhi2"
   [(set (match_operand:HI 0 "general_operand" "=dm")
        (not:HI (match_operand:HI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
   "not%.w %0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
        (not:HI (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "not%.w %0")
 
 (define_insn "one_cmplqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm")
        (not:QI (match_operand:QI 1 "general_operand" "0")))]
-  ""
+  "!TARGET_5200"
   "not%.b %0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
        (not:QI (match_dup 0)))]
-  ""
+  "!TARGET_5200"
   "not%.b %0")
 \f
 ;; arithmetic shift instructions
 } ")
 
 (define_insn "ashldi_sexthi"
-  [(set (match_operand:DI 0 "register_operand" "=*da")
-    (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm"))
-        (const_int 32)))]
+  [(set (match_operand:DI 0 "general_operand" "=m,a*d")
+    (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm,rm"))
+        (const_int 32)))
+    (clobber (match_scratch:SI 2 "=a,X"))]
   ""
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-  if (DATA_REG_P (operands[0]))
-    return \"move%.w %1,%0\;ext%.l %0\;clr%.l %2\";
+  if (GET_CODE (operands[0]) == MEM)
+    {
+    if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+      return \"clr%.l %0\;move%.w %1,%2\;move%.l %2,%0\";
+    else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+      return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %0\";
+    else
+      {
+       operands[3] = adj_offsettable_operand (operands[0], 4);
+       return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %3\";
+      }
+    }
+  else if (DATA_REG_P (operands[0]))
+    return \"move%.w %1,%0\;ext%.l %0\;clr%.l %R0\";
   else
-    return \"move%.w %1,%0\;sub%.l %2,%2\";
+    return \"move%.w %1,%0\;sub%.l %R0,%R0\";
 } ")
 
 (define_insn "ashldi_const32"
-  [(set (match_operand:DI 0 "general_operand" "=ro,<,>")
-       (ashift:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
+  [(set (match_operand:DI 0 "general_operand" "=rm")
+       (ashift:DI (match_operand:DI 1 "general_operand" "ro")
                     (const_int 32)))]
   ""
   "*
     operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
   else
     operands[3] = adj_offsettable_operand (operands[1], 4);
-  if (which_alternative == 1)
-    return \"clr%.l %0\;move%.l %3,%0\";
-  if (which_alternative == 2)
-    return \"move%.l %3,%0\;clr%.l %0\";
   if (GET_CODE (operands[0]) == REG)
     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)
+    return \"move%.l %3,%0\;clr%.l %0\";
   else
     operands[2] = adj_offsettable_operand (operands[0], 4);
   if (ADDRESS_REG_P (operands[2]))
     FAIL;
 } ")
 
-;; 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 ""
+(define_insn "ashlsi_16"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (ashift:SI (match_operand:SI 1 "register_operand" "0")
                   (const_int 16)))]
-  ""
+  "!TARGET_68060"
   "*
 {
   CC_STATUS_INIT;
   return \"swap %0\;clr%.w %0\";
 }")
 
+;; ashift patterns : use lsl instead of asl, because lsl always clears the
+;; overflow bit, so we must not set CC_NO_OVERFLOW.
+
 ;; On the 68000, this makes faster code in a special case.
 
-(define_insn ""
+(define_insn "ashlsi_17_24"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (ashift:SI (match_operand:SI 1 "register_operand" "0")
                   (match_operand:SI 2 "const_int_operand" "n")))]
-  "(! TARGET_68020
+  "(! TARGET_68020 && !TARGET_5200
     && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
   "*
 {
   CC_STATUS_INIT;
 
   operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
-  return \"asl%.w %2,%0\;swap %0\;clr%.w %0\";
+  return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\";
 }")
 
 (define_insn "ashlsi3"
   "*
 {
   if (operands[2] == const1_rtx)
-    return \"add%.l %0,%0\";
-  return \"asl%.l %2,%0\";
+    {
+      cc_status.flags = CC_NO_OVERFLOW;
+      return \"add%.l %0,%0\";
+    }
+  return \"lsl%.l %2,%0\";
 }")
 
 (define_insn "ashlhi3"
   [(set (match_operand:HI 0 "register_operand" "=d")
        (ashift:HI (match_operand:HI 1 "register_operand" "0")
                   (match_operand:HI 2 "general_operand" "dI")))]
-  ""
-  "asl%.w %2,%0")
+  "!TARGET_5200"
+  "lsl%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (ashift:HI (match_dup 0)
                   (match_operand:HI 1 "general_operand" "dI")))]
-  ""
-  "asl%.w %1,%0")
+  "!TARGET_5200"
+  "lsl%.w %1,%0")
 
 (define_insn "ashlqi3"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ashift:QI (match_operand:QI 1 "register_operand" "0")
                   (match_operand:QI 2 "general_operand" "dI")))]
-  ""
-  "asl%.b %2,%0")
+  "!TARGET_5200"
+  "lsl%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
        (ashift:QI (match_dup 0)
                   (match_operand:QI 1 "general_operand" "dI")))]
-  ""
-  "asl%.b %1,%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 ""
+(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.
   [(set (match_operand:SI 0 "register_operand" "=d")
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "n")))]
-  "(! TARGET_68020
+  "(! TARGET_68020 && !TARGET_5200
     && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
   "*
 {
   [(set (match_operand:DI 0 "general_operand" "=d")
        (ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
                     (match_operand 2 "const_int_operand" "n")))]
-  "(INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
+  "!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)"
+    || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 31
+    || INTVAL (operands[2]) == 63))"
   "*
 {
   operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
     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]) == 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)*/
   [(set (match_operand:DI 0 "general_operand" "")
        (ashiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand 2 "const_int_operand" "")))]
-  ""
+  "!TARGET_5200"
   "
 {
   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]) != 16 && INTVAL (operands[2]) != 31
+     && INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 63))
     FAIL;
 } ")
 
+;; On all 68k models, this makes faster code in a special case.
+
+(define_insn "ashrsi_31"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                    (const_int 31)))]
+  ""
+  "*
+{
+  return \"add%.l %0,%0\;subx%.l %0,%0\";
+}")
+
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
   [(set (match_operand:HI 0 "register_operand" "=d")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
                     (match_operand:HI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "asr%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (ashiftrt:HI (match_dup 0)
                     (match_operand:HI 1 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "asr%.w %1,%0")
 
 (define_insn "ashrqi3"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
                     (match_operand:QI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "asr%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
        (ashiftrt:QI (match_dup 0)
                     (match_operand:QI 1 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "asr%.b %1,%0")
 \f
 ;; logical shift instructions
 
-(define_insn ""
-        [(set (cc0)
-            (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
-                    (const_int 32)) 1))
-        (set (match_operand:SI 1 "general_operand" "=dm")
-            (subreg:SI (lshiftrt:DI (match_operand:DI 2 "general_operand" "0")
-                    (const_int 32)) 1))]
-  ""
-  "*
-{
-  return \"move%.l %0,%1\";
-} ")
-
-(define_insn ""
-        [(set (cc0)
-            (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
-                    (const_int 32)) 0))
-        (set (match_operand:DI 1 "general_operand" "=do")
-            (lshiftrt:DI (match_operand:DI 2 "general_operand" "0")
-                (const_int 32)))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[1]) == REG)
-    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\";
-} ")
+;; commented out because of reload problems in 950612-1.c
+;;(define_insn ""
+;;        [(set (cc0)
+;;            (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
+;;                    (const_int 32)) 1))
+;;        (set (match_operand:SI 1 "general_operand" "=dm")
+;;            (subreg:SI (lshiftrt:DI (match_dup 0)
+;;                    (const_int 32)) 1))]
+;;  ""
+;;  "*
+;;{
+;;  return \"move%.l %0,%1\";
+;;} ")
+;;
+;;(define_insn ""
+;;        [(set (cc0)
+;;            (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
+;;                    (const_int 32)) 0))
+;;        (set (match_operand:DI 1 "general_operand" "=do")
+;;            (lshiftrt:DI (match_dup 0)
+;;                (const_int 32)))]
+;;  ""
+;;  "*
+;;{
+;;  if (GET_CODE (operands[1]) == REG)
+;;    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\";
+;;} ")
 
 (define_insn "subreg1lshrdi_const32"
   [(set (match_operand:SI 0 "general_operand" "=rm")
   [(set (match_operand:DI 0 "general_operand" "=d")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
                     (match_operand 2 "const_int_operand" "n")))]
-  "(INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
+  "!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)"
+    || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 63))"
   "*
 {
   operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
   [(set (match_operand:DI 0 "general_operand" "")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand 2 "const_int_operand" "")))]
-  ""
+  "!TARGET_5200"
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT
   return \"add%.l %0,%0\;subx%.l %0,%0\;neg%.l %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 "lshrsi_16"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
                     (const_int 16)))]
-  ""
+  "!TARGET_68060"
   "*
 {
   CC_STATUS_INIT;
   [(set (match_operand:SI 0 "register_operand" "=d")
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "n")))]
-  "(! TARGET_68020
+  "(! TARGET_68020 && !TARGET_5200
     && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
   "*
 {
   [(set (match_operand:HI 0 "register_operand" "=d")
        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
                     (match_operand:HI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "lsr%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (lshiftrt:HI (match_dup 0)
                     (match_operand:HI 1 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "lsr%.w %1,%0")
 
 (define_insn "lshrqi3"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
                     (match_operand:QI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "lsr%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
        (lshiftrt:QI (match_dup 0)
                     (match_operand:QI 1 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "lsr%.b %1,%0")
 \f
 ;; rotate instructions
 (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")))]
-  ""
-  "rol%.l %2,%0")
+                  (match_operand:SI 2 "general_operand" "dINO")))]
+  "!TARGET_5200"
+  "*
+{
+  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_rtx (CONST_INT, VOIDmode, 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")))]
-  ""
-  "rol%.w %2,%0")
-
+                  (match_operand:HI 2 "general_operand" "dIP")))]
+  "!TARGET_5200"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+    {
+      operands[2] = gen_rtx (CONST_INT, VOIDmode, 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")))]
-  ""
-  "rol%.w %1,%0")
+                  (match_operand:HI 1 "general_operand" "dIP")))]
+  "!TARGET_5200"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+    {
+      operands[2] = gen_rtx (CONST_INT, VOIDmode, 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")))]
-  ""
-  "rol%.b %2,%0")
+  "!TARGET_5200"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+    {
+      operands[2] = gen_rtx (CONST_INT, VOIDmode, 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")))]
-  ""
-  "rol%.b %1,%0")
+  "!TARGET_5200"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+    {
+      operands[2] = gen_rtx (CONST_INT, VOIDmode, 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")
        (rotatert:SI (match_operand:SI 1 "register_operand" "0")
                     (match_operand:SI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "ror%.l %2,%0")
 
 (define_insn "rotrhi3"
   [(set (match_operand:HI 0 "register_operand" "=d")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
                     (match_operand:HI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "ror%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (rotatert:HI (match_dup 0)
                     (match_operand:HI 1 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "ror%.w %1,%0")
 
 (define_insn "rotrqi3"
   [(set (match_operand:QI 0 "register_operand" "=d")
        (rotatert:QI (match_operand:QI 1 "register_operand" "0")
                     (match_operand:QI 2 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "ror%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
        (rotatert:QI (match_dup 0)
                     (match_operand:QI 1 "general_operand" "dI")))]
-  ""
+  "!TARGET_5200"
   "ror%.b %1,%0")
 \f
 
 ; than an odd byte aligned bit field instruction.
 ;
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o")
+  [(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"))]
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+do")
                         (match_operand:SI 1 "const_int_operand" "n")
                         (match_operand:SI 2 "const_int_operand" "n"))
        (match_operand:SI 3 "register_operand" "d"))]
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o")
+       (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
                         (const_int 32)
                         (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=&d")
-       (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "do")
                         (match_operand:SI 2 "const_int_operand" "n")
                         (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o")
+       (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
                         (const_int 32)
                         (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=d")
-       (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+       (sign_extract:SI (match_operand:SI 1 "register_operand" "do")
                         (match_operand:SI 2 "const_int_operand" "n")
                         (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
 ;; "o,d" constraint causes a nonoffsettable memref to match the "o"
 ;; so that its address is reloaded.
 
-(define_insn "extv"
-  [(set (match_operand:SI 0 "general_operand" "=d,d")
-       (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
-                        (match_operand:SI 2 "general_operand" "di,di")
-                        (match_operand:SI 3 "general_operand" "di,di")))]
+(define_expand "extv"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (sign_extract:SI (match_operand:SI 1 "general_operand" "")
+                        (match_operand:SI 2 "general_operand" "")
+                        (match_operand:SI 3 "general_operand" "")))]
+  "TARGET_68020 && TARGET_BITFIELD"
+  "")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=d")
+       (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+                        (match_operand:SI 2 "general_operand" "di")
+                        (match_operand:SI 3 "general_operand" "di")))]
   "TARGET_68020 && TARGET_BITFIELD"
   "bfexts %1{%b3:%b2},%0")
 
-(define_insn "extzv"
+(define_expand "extzv"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (zero_extract:SI (match_operand:SI 1 "general_operand" "")
+                        (match_operand:SI 2 "general_operand" "")
+                        (match_operand:SI 3 "general_operand" "")))]
+  "TARGET_68020 && TARGET_BITFIELD"
+  "")
+
+(define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=d,d")
-       (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
+       (zero_extract:SI (match_operand:QI 1 "memory_operand" "o,d")
                         (match_operand:SI 2 "general_operand" "di,di")
                         (match_operand:SI 3 "general_operand" "di,di")))]
   "TARGET_68020 && TARGET_BITFIELD"
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
-                        (match_operand:SI 1 "general_operand" "di,di")
-                        (match_operand:SI 2 "general_operand" "di,di"))
+  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+                        (match_operand:SI 1 "general_operand" "di")
+                        (match_operand:SI 2 "general_operand" "di"))
         (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
-               (match_operand 3 "const_int_operand" "n,n")))]
+               (match_operand 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
    && (INTVAL (operands[3]) == -1
        || (GET_CODE (operands[1]) == CONST_INT
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
-                        (match_operand:SI 1 "general_operand" "di,di")
-                        (match_operand:SI 2 "general_operand" "di,di"))
+  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+                        (match_operand:SI 1 "general_operand" "di")
+                        (match_operand:SI 2 "general_operand" "di"))
        (const_int 0))]
   "TARGET_68020 && TARGET_BITFIELD"
   "*
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
-                        (match_operand:SI 1 "general_operand" "di,di")
-                        (match_operand:SI 2 "general_operand" "di,di"))
+  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+                        (match_operand:SI 1 "general_operand" "di")
+                        (match_operand:SI 2 "general_operand" "di"))
        (const_int -1))]
   "TARGET_68020 && TARGET_BITFIELD"
   "*
   return \"bfset %0{%b2:%b1}\";
 }")
 
-(define_insn "insv"
-  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
-                        (match_operand:SI 1 "general_operand" "di,di")
-                        (match_operand:SI 2 "general_operand" "di,di"))
-       (match_operand:SI 3 "register_operand" "d,d"))]
+(define_expand "insv"
+  [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
+                        (match_operand:SI 1 "general_operand" "")
+                        (match_operand:SI 2 "general_operand" ""))
+       (match_operand:SI 3 "register_operand" ""))]
+  "TARGET_68020 && TARGET_BITFIELD"
+  "")
+
+(define_insn ""
+  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+                        (match_operand:SI 1 "general_operand" "di")
+                        (match_operand:SI 2 "general_operand" "di"))
+       (match_operand:SI 3 "register_operand" "d"))]
   "TARGET_68020 && TARGET_BITFIELD"
   "bfins %3,%0{%b2:%b1}")
 
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=d")
-       (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+       (sign_extract:SI (match_operand:SI 1 "register_operand" "d")
                         (match_operand:SI 2 "general_operand" "di")
                         (match_operand:SI 3 "general_operand" "di")))]
   "TARGET_68020 && TARGET_BITFIELD"
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=d")
-       (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "d")
                         (match_operand:SI 2 "general_operand" "di")
                         (match_operand:SI 3 "general_operand" "di")))]
   "TARGET_68020 && TARGET_BITFIELD"
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
                         (match_operand:SI 1 "general_operand" "di")
                         (match_operand:SI 2 "general_operand" "di"))
        (const_int 0))]
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
                         (match_operand:SI 1 "general_operand" "di")
                         (match_operand:SI 2 "general_operand" "di"))
        (const_int -1))]
 }")
 
 (define_insn ""
-  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
                         (match_operand:SI 1 "general_operand" "di")
                         (match_operand:SI 2 "general_operand" "di"))
        (match_operand:SI 3 "register_operand" "d"))]
 {
   if (operands[1] == const1_rtx
       && GET_CODE (operands[2]) == CONST_INT)
-    {    
+    {
       int width = GET_CODE (operands[0]) == REG ? 31 : 7;
       return output_btst (operands,
                          gen_rtx (CONST_INT, VOIDmode,
   return \"bftst %0{%b2:%b1}\";
 }")
 
-  
+
 ;;; now handle the register cases
 (define_insn ""
   [(set (cc0)
-       (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+       (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
                         (match_operand:SI 1 "const_int_operand" "n")
                         (match_operand:SI 2 "general_operand" "di")))]
   "TARGET_68020 && TARGET_BITFIELD"
 {
   if (operands[1] == const1_rtx
       && GET_CODE (operands[2]) == CONST_INT)
-    {    
+    {
       int width = GET_CODE (operands[0]) == REG ? 31 : 7;
       return output_btst (operands,
                          gen_rtx (CONST_INT, VOIDmode,
   return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
 } ")
 
-(define_insn "seq"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "seq"
+  [(set (match_operand:QI 0 "general_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 "general_operand" "=dm")
        (eq:QI (cc0) (const_int 0)))]
   ""
   "*
   OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
 ")
 
-(define_insn "sne"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sne"
+  [(set (match_operand:QI 0 "general_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 "general_operand" "=dm")
        (ne:QI (cc0) (const_int 0)))]
   ""
   "*
   OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
 ")
 
-(define_insn "sgt"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sgt"
+  [(set (match_operand:QI 0 "general_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 "general_operand" "=dm")
        (gt:QI (cc0) (const_int 0)))]
   ""
   "*
 ")
 
 (define_insn "sgtu"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "general_operand" "=dm")
        (gtu:QI (cc0) (const_int 0)))]
   ""
   "* cc_status = cc_prev_status;
      return \"shi %0\"; ")
 
-(define_insn "slt"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "slt"
+  [(set (match_operand:QI 0 "general_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 "general_operand" "=dm")
        (lt:QI (cc0) (const_int 0)))]
   ""
   "* cc_status = cc_prev_status;
      OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
 
 (define_insn "sltu"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "general_operand" "=dm")
        (ltu:QI (cc0) (const_int 0)))]
   ""
   "* cc_status = cc_prev_status;
      return \"scs %0\"; ")
 
-(define_insn "sge"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sge"
+  [(set (match_operand:QI 0 "general_operand" "")
+       (ge: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 "general_operand" "=dm")
        (ge:QI (cc0) (const_int 0)))]
   ""
   "* cc_status = cc_prev_status;
      OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
 
 (define_insn "sgeu"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "general_operand" "=dm")
        (geu:QI (cc0) (const_int 0)))]
   ""
   "* cc_status = cc_prev_status;
      return \"scc %0\"; ")
 
-(define_insn "sle"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sle"
+  [(set (match_operand:QI 0 "general_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 "general_operand" "=dm")
        (le:QI (cc0) (const_int 0)))]
   ""
   "*
 ")
 
 (define_insn "sleu"
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "general_operand" "=dm")
        (leu:QI (cc0) (const_int 0)))]
   ""
   "* cc_status = cc_prev_status;
   ""
   "*
 {
+  CC_STATUS_INIT;
   if (which_alternative == 1)
 #ifdef MOTOROLA
     return \"move%.l %0,%2\;or%.l %0,%2\;jbeq %l1\";
 #else
     return \"move%.l %0,%2\;or%.l %0,%2\;jeq %l1\";
 #endif
+  if ((cc_prev_status.value1
+      && rtx_equal_p (cc_prev_status.value1, operands[0]))
+    || (cc_prev_status.value2
+      && rtx_equal_p (cc_prev_status.value2, operands[0])))
+    {
+      cc_status = cc_prev_status;
+#ifdef MOTOROLA
+      return \"jbeq %l1\";
+#else
+      return \"jeq %l1\";
+#endif
+    }
   if (GET_CODE (operands[0]) == REG)
     operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
   else
     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]));
             (const_int 0))
         (label_ref (match_operand 1 "" ","))
         (pc)))
-   (clobber (match_scratch:SI 2 "=d,"))]
+   (clobber (match_scratch:SI 2 "=d,X"))]
   ""
   "*
 {
+  if ((cc_prev_status.value1
+      && rtx_equal_p (cc_prev_status.value1, operands[0]))
+    || (cc_prev_status.value2
+      && rtx_equal_p (cc_prev_status.value2, operands[0])))
+    {
+      cc_status = cc_prev_status;
+#ifdef MOTOROLA
+      return \"jbne %l1\";
+#else
+      return \"jne %l1\";
+#endif
+    }
+  CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
     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]))
+#ifdef MOTOROLA
+    return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\";
+#else
+    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
 #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 \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\";
+    return \"cmp%.w %#0,%0\;jbne %l1\;cmp%.w %#0,%3\;jbne %l1\";
+#endif
+#else
+    return \"cmp%.w %#0,%0\;jne %l1\;cmp%.w %#0,%3\;jne %l1\";
 #endif
 } ")
 
   ""
   "*
 {
+  if ((cc_prev_status.value1
+      && rtx_equal_p (cc_prev_status.value1, operands[0]))
+    || (cc_prev_status.value2
+      && rtx_equal_p (cc_prev_status.value2, operands[0])))
+    {
+      cc_status = cc_prev_status;
+      if (cc_status.flags & CC_REVERSED)
+       {
+#ifdef MOTOROLA
+         return \"jble %l1\";
+#else
+         return \"jle %l1\";
+#endif
+       }
+      else
+       {
+#ifdef MOTOROLA
+         return \"jbpl %l1\";
+#else
+         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\;jbge %l1\";
+    return \"jbpl %l1\";
 #else
-  return \"tst%.l %0\;jge %l1\";
+    return \"jpl %l1\";
 #endif
 } ")
 
   ""
   "*
 {
+  if ((cc_prev_status.value1
+      && rtx_equal_p (cc_prev_status.value1, operands[0]))
+    || (cc_prev_status.value2
+      && rtx_equal_p (cc_prev_status.value2, operands[0])))
+    {
+      cc_status = cc_prev_status;
+      if (cc_status.flags & CC_REVERSED)
+       {
+#ifdef MOTOROLA
+         return \"jbgt %l1\";
+#else
+         return \"jgt %l1\";
+#endif
+       }
+      else
+       {
+#ifdef MOTOROLA
+         return \"jbmi %l1\";
+#else
+         return \"jmi %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
 } ")
 
 #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 \"ext%.l %0\;jmp (2,pc,%0.l)\";
+#else
+      return \"extl %0\;jmp pc@(2,%0:l)\";
+#endif
+    }
+  else
+    {
 #ifdef MOTOROLA
-  return \"jmp (2,pc,%0.w)\";
+      return \"jmp (2,pc,%0.w)\";
 #else
-  return \"jmp pc@(2,%0:w)\";
+      return \"jmp pc@(2,%0:w)\";
 #endif
+    }
 #endif
 #endif
 ")
 (define_insn ""
   [(set (pc)
        (if_then_else
-        (ne (match_operand:HI 0 "general_operand" "+g")
+        (ne (match_operand:HI 0 "general_operand" "+d*g")
             (const_int 0))
         (label_ref (match_operand 1 "" ""))
         (pc)))
    (set (match_dup 0)
        (plus:HI (match_dup 0)
                 (const_int -1)))]
-  ""
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
 (define_insn ""
   [(set (pc)
        (if_then_else
-        (ne (match_operand:SI 0 "general_operand" "+g")
+        (ne (match_operand:SI 0 "general_operand" "+d*g")
             (const_int 0))
         (label_ref (match_operand 1 "" ""))
         (pc)))
    (set (match_dup 0)
        (plus:SI (match_dup 0)
                 (const_int -1)))]
-  ""
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
    (set (match_dup 0)
        (plus:HI (match_dup 0)
                 (const_int -1)))]
-  "find_reg_note (insn, REG_NONNEG, 0)"
+  "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)"
   "*
 {
   CC_STATUS_INIT;
 #endif /* not MOTOROLA */
 }")
 
-(define_insn "decrement_and_branch_until_zero"
+(define_expand "decrement_and_branch_until_zero"
+  [(parallel [(set (pc)
+                  (if_then_else
+                   (ge (plus:SI (match_operand:SI 0 "general_operand" "")
+                                (const_int -1))
+                       (const_int 0))
+                   (label_ref (match_operand 1 "" ""))
+                   (pc)))
+             (set (match_dup 0)
+                  (plus:SI (match_dup 0)
+                           (const_int -1)))])]
+  ""
+  "")
+
+(define_insn ""
   [(set (pc)
        (if_then_else
          (ge (plus:SI (match_operand:SI 0 "general_operand" "+d*am")
    (set (match_dup 0)
        (plus:SI (match_dup 0)
                 (const_int -1)))]
-  "find_reg_note (insn, REG_NONNEG, 0)"
+  "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)"
   "*
 {
   CC_STATUS_INIT;
 }")
 
 
-;; PIC calls are handled by loading the address of the function into a 
+;; For PIC calls, in order to be able to support
+;; dynamic linker LAZY BINDING, all the procedure calls need to go
+;; through the PLT (Procedure Linkage Table) section in PIC mode.
+;;
+;; PIC calls are handled by loading the address of the function into a
 ;; register (via movsi), then emitting a register indirect call using
 ;; the "jsr" function call syntax.
 ;;
-;; It is important to note that the "jsr" syntax is always used for 
-;; PIC calls, even on machines in which GCC normally uses the "jbsr"
-;; syntax for non-PIC calls.  This keeps at least 1 assembler (Sun)
-;; from emitting incorrect code for a PIC call.
+;; When outputting MIT syntax (e.g. on Suns), we add a bogus extra
+;; operand to the jbsr statement to indicate that this call should
+;; go through the PLT (why? because this is the way that Sun does it).
 ;;
 ;; We have different patterns for PIC calls and non-PIC calls.  The
-;; different patterns are only used to choose the right syntax
-;; ("jsr" vs "jbsr").
+;; different patterns are only used to choose the right syntax.
 ;;
-;; On svr4 m68k, PIC stuff is done differently. To be able to support
-;; dynamic linker LAZY BINDING, all the procedure calls need to go 
-;; through the PLT (Procedure Linkage Table) section in PIC mode. The 
-;; svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it 
-;; will create the correct relocation entry (R_68K_PLT32) for `FUNC', 
+;; The svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it
+;; will create the correct relocation entry (R_68K_PLT32) for `FUNC',
 ;; that tells the linker editor to create an entry for `FUNC' in PLT
 ;; section at link time. However, all global objects reference are still
-;; done by using `OBJ@GOT'. So, the goal here is to output the function 
-;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'. 
+;; done by using `OBJ@GOT'. So, the goal here is to output the function
+;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'.
 ;; We need to have a way to differentiate these two different operands.
 ;;
-;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate 
+;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate
 ;; these two different operands. The macro LEGITIMATE_PIC_OPERAND_P needs
-;; to be changed to recognize function calls symbol_ref operand as a valid 
-;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will 
-;; avoid the compiler to load this symbol_ref operand into a register. 
-;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly 
+;; to be changed to recognize function calls symbol_ref operand as a valid
+;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will
+;; avoid the compiler to load this symbol_ref operand into a register.
+;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly
 ;; since the value is a PC relative offset, not a real address.
 ;;
-;; All global objects are treated in the similar way as in SUN3. The only 
-;; difference is: on m68k svr4, the reference of such global object needs 
+;; All global objects are treated in the similar way as in SUN3. The only
+;; difference is: on m68k svr4, the reference of such global object needs
 ;; to end with a suffix "@GOT" so the assembler and linker know to create
-;; an entry for it in GOT (Global Offset Table) section. This is done in 
+;; an entry for it in GOT (Global Offset Table) section. This is done in
 ;; m68k.c.
 
 ;; Call subroutine with no return value.
   "
 {
   if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
-#ifdef MOTOROLA
     SYMBOL_REF_FLAG (XEXP (operands[0], 0)) = 1;
-#else
-    operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
-                          force_reg (Pmode, XEXP (operands[0], 0)));
-#endif
 }")
 
 ;; This is a normal call sequence.
 
   "! flag_pic"
   "*
-#ifdef MOTOROLA
+#if defined (MOTOROLA) && !defined (USE_GAS)
 #ifdef MOTOROLA_BSR
-  if (GET_CODE (operands[0]) == MEM 
+  if (GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
     return \"bsr %0\";
 #endif
 
   "flag_pic"
   "*
-#ifdef MOTOROLA
-  if (GET_CODE (operands[0]) == MEM 
+  if (GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+#ifdef MOTOROLA
 #ifdef HPUX_ASM
     return \"bsr.l %0\";
 #else
+#ifdef USE_GAS
+    return \"bsr.l %0@PLTPC\";
+#else
     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\";
+#endif
   return \"jsr %0\";
 ")
 
   "
 {
   if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
-#ifdef MOTOROLA
     SYMBOL_REF_FLAG (XEXP (operands[1], 0)) = 1;
-#else
-    operands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
-                          force_reg (Pmode, XEXP (operands[1], 0)));
-#endif
 }")
 
 ;; This is a normal call_value
   ;; Operand 2 not really used on the m68000.
   "! flag_pic"
   "*
-#ifdef MOTOROLA
+#if defined (MOTOROLA) && !defined (USE_GAS)
 #ifdef MOTOROLA_BSR
-  if (GET_CODE (operands[1]) == MEM 
+  if (GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
     return \"bsr %1\";
 #endif
   ;; Operand 2 not really used on the m68000.
   "flag_pic"
   "*
-#ifdef MOTOROLA
-  if (GET_CODE (operands[1]) == MEM 
+  if (GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+#ifdef MOTOROLA
 #ifdef HPUX_ASM
     return \"bsr.l %1\";
 #else
+#ifdef USE_GAS
+    return \"bsr.l %1@PLTPC\";
+#else
     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\";
+#endif
   return \"jsr %1\";
 ")
 
       xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
 #ifndef NO_ADDSUB_Q
       if (INTVAL (xoperands[1]) <= 8)
-        output_asm_insn (\"addq%.w %1,%0\", xoperands);
-      else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
        {
-         xoperands[1] = gen_rtx (CONST_INT, VOIDmode, 
+         if (!TARGET_5200)
+           output_asm_insn (\"addq%.w %1,%0\", xoperands);
+         else
+           output_asm_insn (\"addq%.l %1,%0\", xoperands);
+       }
+      else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16) 
+       {
+         xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
                                  INTVAL (xoperands[1]) - 8);
          output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
        }
       else
 #endif
         if (INTVAL (xoperands[1]) <= 0x7FFF)
-          output_asm_insn (\"add%.w %1,%0\", xoperands);
+        {
+         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] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
 #ifndef NO_ADDSUB_Q
       if (INTVAL (xoperands[1]) <= 8)
-        output_asm_insn (\"addq%.w %1,%0\", xoperands);
-      else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
        {
-         xoperands[1] = gen_rtx (CONST_INT, VOIDmode, 
+         if (!TARGET_5200)
+           output_asm_insn (\"addq%.w %1,%0\", xoperands);
+         else
+           output_asm_insn (\"addq%.l %1,%0\", xoperands);
+       }
+      else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
+       {
+         xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
                                  INTVAL (xoperands[1]) - 8);
          output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
        }
       else
 #endif
         if (INTVAL (xoperands[1]) <= 0x7FFF)
-          output_asm_insn (\"add%.w %1,%0\", xoperands);
+        {
+         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);
     }
               gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
                        gen_rtx (CONST_INT, VOIDmode, 3)));
   xoperands[3] = stack_pointer_rtx;
-  output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
+  if (!TARGET_5200)
+    output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
+  else
+    output_asm_insn (\"subq%.l %#4,%3\;move%.b %1,%2\", xoperands);
   return \"\";
 }")
 
          && (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 alternative for it.  */
-         && (TARGET_68020
+            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\";
      (set (match_dup 0)
          (plus:HI (match_dup 0)
                   (const_int -1)))])]
-  "DATA_REG_P (operands[0])"
+  "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
   "*
 {
   CC_STATUS_INIT;
      (set (match_dup 0)
          (plus:SI (match_dup 0)
                   (const_int -1)))])]
-  "DATA_REG_P (operands[0])"
+  "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
   "*
 {
   CC_STATUS_INIT;
    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_expand "cmpxf"
   [(set (cc0)
-       (compare (match_operand:XF 0 "general_operand" "f,mG")
-                (match_operand:XF 1 "general_operand" "fmG,f")))]
+       (compare (match_operand:XF 0 "nonimmediate_operand" "")
+                (match_operand:XF 1 "nonimmediate_operand" "")))]
   "TARGET_68881"
-  "
-{
-  if (CONSTANT_P (operands[0]))
-      operands[0] = force_const_mem (XFmode, operands[0]);
-  if (CONSTANT_P (operands[1]))
-      operands[1] = force_const_mem (XFmode, operands[1]);
-}")
+  "m68k_last_compare_had_fp_operands = 1;")
 
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:XF 0 "nonimmediate_operand" "f,mG")
-                (match_operand:XF 1 "nonimmediate_operand" "fmG,f")))]
+       (compare (match_operand:XF 0 "nonimmediate_operand" "f,m")
+                (match_operand:XF 1 "nonimmediate_operand" "fm,f")))]
   "TARGET_68881"
   "*
 {
     }
   return \"fmove%.d %f1,%0\";
 }")
+
 (define_insn "truncxfsf2"
   [(set (match_operand:SF 0 "general_operand" "=dm")
        (float_truncate:SF
   "TARGET_68881"
   "fmove%.l %1,%0")
 
-(define_expand "addxf3"
-  [(set (match_operand:XF 0 "general_operand" "")
-       (plus:XF (match_operand:XF 1 "general_operand" "")
-                (match_operand:XF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "
-{
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_const_mem (XFmode, operands[1]);
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (XFmode, operands[2]);
-}")
-
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
        (plus:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:XF 1 "general_operand" "0")))]
+                (match_operand:XF 1 "nonimmediate_operand" "0")))]
   "TARGET_68881"
   "fadd%.l %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
        (plus:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "general_operand" "0")))]
+                (match_operand:XF 1 "nonimmediate_operand" "0")))]
   "TARGET_68881"
   "fadd%.w %2,%0")
 
   "TARGET_68881"
   "fadd%.b %2,%0")
 
-(define_insn ""
+(define_insn "addxf3"
   [(set (match_operand:XF 0 "general_operand" "=f")
        (plus:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
-                (match_operand:XF 2 "nonimmediate_operand" "fmG")))]
+                (match_operand:XF 2 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
   "*
 {
   return \"fadd%.x %f2,%0\";
 }")
 
-(define_expand "subxf3"
-  [(set (match_operand:XF 0 "general_operand" "")
-       (minus:XF (match_operand:XF 1 "general_operand" "")
-                (match_operand:XF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "
-{
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_const_mem (XFmode, operands[1]);
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (XFmode, operands[2]);
-}")
-
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (minus:XF (match_operand:XF 1 "general_operand" "0")
+       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
                  (float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
   "TARGET_68881"
   "fsub%.l %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (minus:XF (match_operand:XF 1 "general_operand" "0")
+       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
                  (float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
   "fsub%.w %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (minus:XF (match_operand:XF 1 "general_operand" "0")
+       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
                  (float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
   "fsub%.b %2,%0")
 
-(define_insn ""
+(define_insn "subxf3"
   [(set (match_operand:XF 0 "general_operand" "=f")
        (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-                (match_operand:XF 2 "nonimmediate_operand" "fmG")))]
+                 (match_operand:XF 2 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
   "*
 {
   return \"fsub%.x %f2,%0\";
 }")
 
-(define_expand "mulxf3"
-  [(set (match_operand:XF 0 "general_operand" "")
-       (mult:XF (match_operand:XF 1 "general_operand" "")
-               (match_operand:XF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "
-{
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_const_mem (XFmode, operands[1]);
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (XFmode, operands[2]);
-}")
-
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
        (mult:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:XF 1 "general_operand" "0")))]
+                (match_operand:XF 1 "nonimmediate_operand" "0")))]
   "TARGET_68881"
   "fmul%.l %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
        (mult:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "general_operand" "0")))]
+                (match_operand:XF 1 "nonimmediate_operand" "0")))]
   "TARGET_68881"
   "fmul%.w %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
        (mult:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "general_operand" "0")))]
+                (match_operand:XF 1 "nonimmediate_operand" "0")))]
   "TARGET_68881"
   "fmul%.b %2,%0")
 
-(define_insn ""
+(define_insn "mulxf3"
   [(set (match_operand:XF 0 "general_operand" "=f")
        (mult:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
-               (match_operand:XF 2 "nonimmediate_operand" "fmG")))]
+                (match_operand:XF 2 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
   "*
 {
   return \"fmul%.x %f2,%0\";
 }")
 
-(define_expand "divxf3"
-  [(set (match_operand:XF 0 "general_operand" "")
-       (div:XF (match_operand:XF 1 "general_operand" "")
-               (match_operand:XF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "
-{
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_const_mem (XFmode, operands[1]);
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (XFmode, operands[2]);
-}")
-
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (div:XF (match_operand:XF 1 "general_operand" "0")
+       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
                (float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
   "TARGET_68881"
   "fdiv%.l %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (div:XF (match_operand:XF 1 "general_operand" "0")
+       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
                (float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
   "fdiv%.w %2,%0")
 
 (define_insn ""
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (div:XF (match_operand:XF 1 "general_operand" "0")
+       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
                (float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
   "fdiv%.b %2,%0")
 
-(define_insn ""
+(define_insn "divxf3"
   [(set (match_operand:XF 0 "general_operand" "=f")
        (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-               (match_operand:XF 2 "nonimmediate_operand" "fmG")))]
+               (match_operand:XF 2 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
   "*
 {
 
 (define_expand "negxf2"
   [(set (match_operand:XF 0 "general_operand" "")
-       (neg:XF (match_operand:XF 1 "general_operand" "")))]
+       (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
   ""
   "
 {
   /* ??? There isn't an FPA define_insn so we could handle it here too.
      For now we don't (paranoia).  */
-  if (!TARGET_FPA && !TARGET_68881)
+  if (!TARGET_68881)
     {
       rtx result;
       rtx target;
 
       if (result != target)
        emit_move_insn (result, target);
-  
+
       emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
                      operand_subword_force (operands[1], 1, XFmode));
       emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
 
 (define_insn "negxf2_68881"
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (neg:XF (match_operand:XF 1 "nonimmediate_operand" "fmF")))]
+       (neg:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
   "*
 {
 
 (define_expand "absxf2"
   [(set (match_operand:XF 0 "general_operand" "")
-       (abs:XF (match_operand:XF 1 "general_operand" "")))]
+       (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
   ""
   "
 {
   /* ??? There isn't an FPA define_insn so we could handle it here too.
      For now we don't (paranoia).  */
-  if (!TARGET_FPA && !TARGET_68881)
+  if (!TARGET_68881)
     {
       rtx result;
       rtx target;
 
       if (result != target)
        emit_move_insn (result, target);
-  
+
       emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
                      operand_subword_force (operands[1], 1, XFmode));
       emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
 
 (define_insn "absxf2_68881"
   [(set (match_operand:XF 0 "general_operand" "=f")
-       (abs:XF (match_operand:XF 1 "nonimmediate_operand" "fmF")))]
+       (abs:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
   "*
 {
   [(set (match_operand:XF 0 "general_operand" "=f")
        (sqrt:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
-  "*
-{
-    return \"fsqrt%.x %1,%0\";
-}")
+  "fsqrt%.x %1,%0")
 
 (define_insn "sinsf2"
   [(set (match_operand:SF 0 "general_operand" "=f")
   [(set (match_operand:XF 0 "general_operand" "=f")
        (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 1))]
   "TARGET_68881 && flag_fast_math"
-  "*
-{
-    return \"fsin%.x %1,%0\";
-}")
+  "fsin%.x %1,%0")
 
 (define_insn "cossf2"
   [(set (match_operand:SF 0 "general_operand" "=f")
   [(set (match_operand:XF 0 "general_operand" "=f")
        (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
   "TARGET_68881 && flag_fast_math"
-  "*
-{
-    return \"fcos%.x %1,%0\";
-}")
+  "fcos%.x %1,%0")