OSDN Git Service

* genoutput.c (validate_insn_operands): New.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.md
index 83d5c83..75c5525 100644 (file)
@@ -1,5 +1,6 @@
 ;;- Machine description for GNU compiler, Motorola 68000 Version
-;;  Copyright (C) 1987, 88, 93-98, 1999 Free Software Foundation, Inc.
+;;  Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999
+;;  Free Software Foundation, Inc.
 
 ;; This file is part of GNU CC.
 
   "
 {
   m68k_last_compare_had_fp_operands = 0;
-  if (flag_pic && symbolic_operand (operands[1], SImode))
+  if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
     {
       /* The source is an address which requires PIC relocation.
          Call legitimize_pic_address with the source, mode, and a relocation
          register (a new pseudo, or the final destination if reload_in_progress
          is set).   Then fall through normally */
-      extern rtx legitimize_pic_address();
       rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
       operands[1] = legitimize_pic_address (operands[1], SImode, temp);
     }
 ;; 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,rKs,>")))]
+        (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mSr,mSa,>")
+                 (match_operand:SI 1 "general_src_operand" "mSr,mSa,KTr,Ksr,>")))]
   "!TARGET_5200"
   "*
 {
       return \"cmp%.l %d0,%d1\";
 #endif
     }
+  if (ADDRESS_REG_P (operands[0])
+      && GET_CODE (operands[1]) == CONST_INT
+      && INTVAL (operands[1]) < 0x8000
+      && INTVAL (operands[1]) >= -0x8000)
+    {
+#ifdef SGS_CMP_ORDER
+      return \"cmp%.w %0,%1\";
+#else
+      return \"cmp%.w %1,%0\";
+#endif
+    }
 #ifdef SGS_CMP_ORDER
   return \"cmp%.l %d0,%d1\";
 #else
 
 (define_expand "cmphi"
   [(set (cc0)
-       (compare (match_operand:HI 0 "nonimmediate_operand" "")
-                (match_operand:HI 1 "general_operand" "")))]
+        (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
+                 (match_operand:HI 1 "general_src_operand" "")))]
   "!TARGET_5200"
   "m68k_last_compare_had_fp_operands = 0;")
 
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
-                (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+        (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>")
+                 (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))]
   "!TARGET_5200"
   "*
 {
 
 (define_expand "cmpqi"
   [(set (cc0)
-       (compare (match_operand:QI 0 "nonimmediate_operand" "")
-                (match_operand:QI 1 "general_operand" "")))]
+        (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
+                 (match_operand:QI 1 "general_src_operand" "")))]
   "!TARGET_5200"
   "m68k_last_compare_had_fp_operands = 0;")
 
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>")
-                (match_operand:QI 1 "general_operand" "dm,nd,>")))]
+        (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>")
+                 (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))]
   "!TARGET_5200"
   "*
 {
 ;; from a MEM at a constant bit position if we can't use this as a constraint.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
+  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_src_operand" "oS")
                            (const_int 1)
                            (minus:SI (const_int 7)
                                      (match_operand:SI 1 "general_operand" "di"))))]
   ""
   "
 {
-  if (flag_pic && symbolic_operand (operands[1], SImode))
+  if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
     {
       /* The source is an address which requires PIC relocation.
          Call legitimize_pic_address with the source, mode, and a relocation
          register (a new pseudo, or the final destination if reload_in_progress
          is set).   Then fall through normally */
-      extern rtx legitimize_pic_address();
       rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
       operands[1] = legitimize_pic_address (operands[1], SImode, temp);
     }
+  else if (flag_pic && TARGET_PCREL && ! reload_in_progress)
+    {
+      /* Don't allow writes to memory except via a register;
+        the m68k doesn't consider PC-relative addresses to be writable.  */
+      if (symbolic_operand (operands[0], SImode))
+       operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+      else if (GET_CODE (operands[0]) == MEM
+              && symbolic_operand (XEXP (operands[0], 0), SImode))
+       operands[0] = gen_rtx (MEM, SImode,
+                              force_reg (SImode, XEXP (operands[0], 0)));
+    }
 }")
 
 ;; General case of fullword move.  The register constraints
   ;; Notes: make sure no alternative allows g vs g.
   ;; We don't allow f-regs since fixed point cannot go in them.
   ;; We do allow y and x regs since fixed point is allowed in them.
-  [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
-       (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
+  [(set (match_operand:SI 0 "general_operand" "=g,d,a<,y,!*x*r*m")
+        (match_operand:SI 1 "general_src_operand" "daymSKT,n,i,g,*x*r*m"))]
+
   "!TARGET_5200"
   "*
 {
-  if (which_alternative == 3)
+  if (which_alternative == 4)
     return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
   if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
     return \"fpmove%.l %x1,%x0\";
   "TARGET_5200"
   "* return output_move_simode (operands);")
 
+;; Special case of fullword move, where we need to get a non-GOT PIC
+;; reference into an address register.
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=a<")
+        (match_operand:SI 1 "pcrel_address" ""))]
+  "TARGET_PCREL"
+  "*
+{
+  if (push_operand (operands[0], SImode))
+    return \"pea %a1\";
+  return \"lea %a1,%0\";
+}")
+
 (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"))]
+        (match_operand:HI 1 "general_src_operand" "gS"))]
   "!TARGET_5200"
   "* return output_move_himode (operands);")
 
 
 (define_expand "movstricthi"
   [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
-       (match_operand:HI 1 "general_operand" ""))]
+        (match_operand:HI 1 "general_src_operand" ""))]
   ""
   "")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
-       (match_operand:HI 1 "general_operand" "rmn"))]
+       (match_operand:HI 1 "general_src_operand" "rmSn"))]
   "!TARGET_5200"
   "* return output_move_stricthi (operands);")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+d,m"))
-       (match_operand:HI 1 "general_operand" "rmn,r"))]
+       (match_operand:HI 1 "general_src_operand" "rmn,r"))]
   "TARGET_5200"
   "* return output_move_stricthi (operands);")
 
 (define_expand "movqi"
   [(set (match_operand:QI 0 "general_operand" "")
-       (match_operand:QI 1 "general_operand" ""))]
+        (match_operand:QI 1 "general_src_operand" ""))]
   ""
   "")
 
 (define_insn ""
   [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
-       (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))]
+       (match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
   "!TARGET_5200"
   "* return output_move_qimode (operands);")
 
 (define_insn ""
   [(set (match_operand:QI 0 "general_operand" "=d<Q>,dm,d*a")
-       (match_operand:QI 1 "general_operand" "dmi,d<Q>,di*a"))]
+       (match_operand:QI 1 "general_src_operand" "dmi,d<Q>,di*a"))]
   "TARGET_5200"
   "* return output_move_qimode (operands);")
 
 (define_expand "movstrictqi"
   [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
-       (match_operand:QI 1 "general_operand" ""))]
+        (match_operand:QI 1 "general_src_operand" ""))]
   ""
   "")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
-       (match_operand:QI 1 "general_operand" "dmn"))]
+       (match_operand:QI 1 "general_src_operand" "dmSn"))]
   "!TARGET_5200"
   "* return output_move_strictqi (operands);")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+d,m"))
-       (match_operand:QI 1 "general_operand" "dmn,d"))]
+       (match_operand:QI 1 "general_src_operand" "dmn,d"))]
   "TARGET_5200"
   "* return output_move_strictqi (operands);")
 
   "")
 
 (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,*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"
        operands[1] = change_address (operands[1], XFmode,
                                      XEXP (operands[1], 0));
     }
+  if (flag_pic && TARGET_PCREL && ! reload_in_progress)
+    {
+      /* Don't allow writes to memory except via a register;
+        the m68k doesn't consider PC-relative addresses to be writable.  */
+      if (GET_CODE (operands[0]) == MEM
+         && symbolic_operand (XEXP (operands[0], 0), SImode))
+       operands[0] = gen_rtx (MEM, XFmode,
+                              force_reg (SImode, XEXP (operands[0], 0)));
+    }
 }")
 
 (define_insn ""
 (define_insn "truncsiqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm,d")
        (truncate:QI
-        (match_operand:SI 1 "general_operand" "doJ,i")))]
+        (match_operand:SI 1 "general_src_operand" "doJS,i")))]
   ""
   "*
 {
 (define_insn "trunchiqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm,d")
        (truncate:QI
-        (match_operand:HI 1 "general_operand" "doJ,i")))]
+        (match_operand:HI 1 "general_src_operand" "doJS,i")))]
   ""
   "*
 {
 (define_insn "truncsihi2"
   [(set (match_operand:HI 0 "general_operand" "=dm,d")
        (truncate:HI
-        (match_operand:SI 1 "general_operand" "roJ,i")))]
+        (match_operand:SI 1 "general_src_operand" "roJS,i")))]
   ""
   "*
 {
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   return \"moveq %#0,%0\;moveq %#0,%2\;move%.b %1,%2\";
 }")
 
   "*
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   return \"moveq %#0,%0\;moveq %#0,%2\;move%.w %1,%2\";
 }")
 
 ;; this is the canonical form for (lshiftrt:DI x 32)
 (define_insn "zero_extendsidi2"
-  [(set (match_operand:DI 0 "general_operand" "rm")
+  [(set (match_operand:DI 0 "general_operand" "=rm")
     (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
   ""
   "*
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=do<>,d<")
-       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn ""
   [(set (match_operand:HI 0 "general_operand" "=do<>,d")
-       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+       (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=do<>,d")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn "extendqidi2"
   [(set (match_operand:DI 0 "general_operand" "=d")
-       (sign_extend:DI
-        (match_operand:QI 1 "general_operand" "rm")))]
+        (sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
   ""
   "*
 {
 (define_insn "extendhidi2"
   [(set (match_operand:DI 0 "general_operand" "=d")
        (sign_extend:DI
-        (match_operand:HI 1 "general_operand" "rm")))]
+        (match_operand:HI 1 "general_src_operand" "rmS")))]
   ""
   "*
 {
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "general_operand" "=*d,a")
        (sign_extend:SI
-        (match_operand:HI 1 "nonimmediate_operand" "0,rm")))]
+        (match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))]
   ""
   "*
 {
        return \"add%.l %R2,%R0\;addx%.l %2,%0\";
       else if (GET_CODE (operands[2]) == MEM
          && GET_CODE (XEXP (operands[2], 0)) == POST_INC)
-       {
-         return \"move%.l %2,%3\;add%.l %2,%R0\;addx%.l %3,%0\";
-       }
+       return \"move%.l %2,%3\;add%.l %2,%R0\;addx%.l %3,%0\";
       else
        {
+         rtx high, low;
          rtx xoperands[2];
+
          if (GET_CODE (operands[2]) == REG)
-           operands[1] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
-         else if (GET_CODE (operands[2]) == CONST_DOUBLE)
            {
-             operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-             operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+             low = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+             high = operands[2];
            }
-         else if (GET_CODE (operands[2]) == CONST_INT)
+         else if (CONSTANT_P (operands[2]))
+           split_double (operands[2], &high, &low);
+         else
            {
-             operands[1] = operands[2];
-             operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+             low = adj_offsettable_operand (operands[2], 4);
+             high = operands[2];
            }
-         else
-           operands[1] = adj_offsettable_operand (operands[2], 4);
+
+         operands[1] = low, operands[2] = high;
          xoperands[0] = operands[3];
          if (GET_CODE (operands[1]) == CONST_INT
              && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
            xoperands[1] = GEN_INT (-INTVAL (operands[2]) - 1);
          else
            xoperands[1] = operands[2];
+
          output_asm_insn (output_move_simode (xoperands), xoperands);
          if (GET_CODE (operands[1]) == CONST_INT)
            {
       CC_STATUS_INIT;
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
        {
-         operands[1]
-           = gen_rtx_MEM (SImode,
-                          gen_rtx_PLUS (VOIDmode, XEXP(operands[0], 0),
-                                        GEN_INT (-8)));
+         operands[1] = gen_rtx_MEM (SImode,
+                                    plus_constant (XEXP(operands[0], 0), -8));
          return \"move%.l %0,%3\;add%.l %R2,%0\;addx%.l %2,%3\;move%.l %3,%1\";
        }
       else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
 (define_expand "addsi3"
   [(set (match_operand:SI 0 "general_operand" "")
        (plus:SI (match_operand:SI 1 "general_operand" "")
-                (match_operand:SI 2 "general_operand" "")))]
+                (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 ;; This is needed since they are not themselves reloaded,
 ;; so commutativity won't apply to them.
 (define_insn "*addsi3_internal"
-  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
-       (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
-                (match_operand:SI 2 "general_operand" "dIKLs,rJK,a,mrIKLs")))]
+  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,d,a")
+        (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0")
+                 (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))]
+
+
   "! TARGET_5200"
   "* return output_addsi3 (operands);")
 
 (define_insn "*addsi3_5200"
   [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
        (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
-                (match_operand:SI 2 "general_operand" "d,rJK,a,mrIKLs")))]
+                (match_operand:SI 2 "general_src_operand" "d,rJK,a,mrIKLs")))]
   "TARGET_5200"
   "* return output_addsi3 (operands);")
 
   [(set (match_operand:SI 0 "general_operand" "=a")
        (plus:SI (match_operand:SI 1 "general_operand" "0")
                 (sign_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
   "!TARGET_5200"
   "add%.w %2,%0")
 
 (define_insn "addhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,r")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
-                (match_operand:HI 2 "general_operand" "dn,rmn")))]
+                (match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "*
 {
       if (INTVAL (operands[2]) < 0
          && INTVAL (operands[2]) >= -8)
        {
-         operands[2] = GEN_INT (-INTVAL (operands[2]));
+         operands[2] = GEN_INT (- INTVAL (operands[2]));
          return \"subq%.w %2,%0\";
        }
       /* On the CPU32 it is faster to use two addqw instructions to
          if (INTVAL (operands[2]) < -8
              && INTVAL (operands[2]) >= -16)
            {
-             operands[2] = GEN_INT (-INTVAL (operands[2]) - 8);
+             operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
              return \"subq%.w %#8,%0\;subq%.w %2,%0\";
            }
        }
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (plus:HI (match_dup 0)
-                (match_operand:HI 1 "general_operand" "dn,rmn")))]
+                (match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "*
 {
       if (INTVAL (operands[1]) < 0
          && INTVAL (operands[1]) >= -8)
        {
-         operands[1] = GEN_INT (-INTVAL (operands[1]));
+         operands[1] = GEN_INT (- INTVAL (operands[1]));
          return \"subq%.w %1,%0\";
        }
       /* On the CPU32 it is faster to use two addqw instructions to
          if (INTVAL (operands[1]) < -8
              && INTVAL (operands[1]) >= -16)
            {
-             operands[1] = GEN_INT (-INTVAL (operands[1]) - 8);
+             operands[1] = GEN_INT (- INTVAL (operands[1]) - 8);
              return \"subq%.w %#8,%0\;subq%.w %1,%0\";
            }
        }
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
+       (plus:HI (match_operand:HI 1 "general_src_operand" "dn,rmSn")
                 (match_dup 0)))]
   "!TARGET_5200"
   "*
       if (INTVAL (operands[1]) < 0
          && INTVAL (operands[1]) >= -8)
        {
-         operands[1] = GEN_INT (-INTVAL (operands[1]));
+         operands[1] = GEN_INT (- INTVAL (operands[1]));
          return \"subq%.w %1,%0\";
        }
       /* On the CPU32 it is faster to use two addqw instructions to
          if (INTVAL (operands[1]) < -8
              && INTVAL (operands[1]) >= -16)
            {
-             operands[1] = GEN_INT (-INTVAL (operands[1]) - 8);
+             operands[1] = GEN_INT (- INTVAL (operands[1]) - 8);
              return \"subq%.w %#8,%0\;subq%.w %1,%0\";
            }
        }
 (define_insn "addqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
-                (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "*
 {
        return \"addq%.b %2,%0\";
       if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8)
        {
-        operands[2] = GEN_INT (-INTVAL (operands[2]));
+        operands[2] = GEN_INT (- INTVAL (operands[2]));
         return \"subq%.b %2,%0\";
        }
     }
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (plus:QI (match_dup 0)
-                (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "*
 {
        return \"addq%.b %1,%0\";
       if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
        {
-        operands[1] = GEN_INT (-INTVAL (operands[1]));
+        operands[1] = GEN_INT (- INTVAL (operands[1]));
         return \"subq%.b %1,%0\";
        }
     }
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+       (plus:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                 (match_dup 0)))]
   "!TARGET_5200"
   "*
        return \"addq%.b %1,%0\";
       if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
        {
-        operands[1] = GEN_INT (-INTVAL (operands[1]));
+        operands[1] = GEN_INT (- INTVAL (operands[1]));
         return \"subq%.b %1,%0\";
        }
     }
        }
       else
        {
+         rtx high, low;
          rtx xoperands[2];
+
          if (GET_CODE (operands[2]) == REG)
-           operands[1] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
-         else if (GET_CODE (operands[2]) == CONST_DOUBLE)
            {
-             operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-             operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+             low = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+             high = operands[2];
            }
-         else if (GET_CODE (operands[2]) == CONST_INT)
+         else if (CONSTANT_P (operands[2]))
+           split_double (operands[2], &high, &low);
+         else
            {
-             operands[1] = operands[2];
-             operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+             low = adj_offsettable_operand (operands[2], 4);
+             high = operands[2];
            }
-         else
-           operands[1] = adj_offsettable_operand (operands[2], 4);
+
+         operands[1] = low, operands[2] = high;
          xoperands[0] = operands[3];
          if (GET_CODE (operands[1]) == CONST_INT
              && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
            xoperands[1] = GEN_INT (-INTVAL (operands[2]) - 1);
          else
            xoperands[1] = operands[2];
+
          output_asm_insn (output_move_simode (xoperands), xoperands);
          if (GET_CODE (operands[1]) == CONST_INT)
            {
       if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
        {
          operands[1]
-           = gen_rtx_MEM (SImode,
-                          gen_rtx_PLUS (VOIDmode, XEXP(operands[0], 0),
-                                        GEN_INT (-8)));
+           = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[0], 0), -8));
          return \"move%.l %0,%3\;sub%.l %R2,%0\;subx%.l %2,%3\;move%.l %3,%1\";
        }
       else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
 } ")
 
 (define_insn "subsi3"
-  [(set (match_operand:SI 0 "general_operand" "=m,r")
-       (minus:SI (match_operand:SI 1 "general_operand" "0,0")
-                 (match_operand:SI 2 "general_operand" "ds,mrs")))]
+  [(set (match_operand:SI 0 "general_operand" "=m,d,a")
+       (minus:SI (match_operand:SI 1 "general_operand" "0,0,0")
+                 (match_operand:SI 2 "general_src_operand" "dT,mSrT,mSrs")))]
   ""
   "sub%.l %2,%0")
 
   [(set (match_operand:SI 0 "general_operand" "=a")
        (minus:SI (match_operand:SI 1 "general_operand" "0")
                  (sign_extend:SI
-                  (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+                  (match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
   "!TARGET_5200"
   "sub%.w %2,%0")
 
 (define_insn "subhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,r")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
-                 (match_operand:HI 2 "general_operand" "dn,rmn")))]
+                 (match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "sub%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (minus:HI (match_dup 0)
-                 (match_operand:HI 1 "general_operand" "dn,rmn")))]
+                 (match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "sub%.w %1,%0")
 
 (define_insn "subqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (minus:QI (match_operand:QI 1 "general_operand" "0,0")
-                 (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                 (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "sub%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (minus:QI (match_dup 0)
-                 (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                 (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "sub%.b %1,%0")
 
 (define_insn "mulhi3"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (mult:HI (match_operand:HI 1 "general_operand" "%0")
-                (match_operand:HI 2 "general_operand" "dmn")))]
+                (match_operand:HI 2 "general_src_operand" "dmSn")))]
   ""
   "*
 {
        (mult:SI (sign_extend:SI
                  (match_operand:HI 1 "nonimmediate_operand" "%0"))
                 (sign_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "dmS"))))]
   ""
   "*
 {
 (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")))]
+                 (match_operand:SI 2 "general_src_operand" "dmSTK")))]
+
   "TARGET_68020"
   "muls%.l %2,%0")
 
        (mult:SI (zero_extend:SI
                  (match_operand:HI 1 "nonimmediate_operand" "%0"))
                 (zero_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "dmS"))))]
   ""
   "*
 {
 (define_insn "divmodsi4"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (div:SI (match_operand:SI 1 "general_operand" "0")
-               (match_operand:SI 2 "general_operand" "dmsK")))
+               (match_operand:SI 2 "general_src_operand" "dmSTK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (mod:SI (match_dup 1) (match_dup 2)))]
   "TARGET_68020 && !TARGET_5200"
 (define_insn "udivmodsi4"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (udiv:SI (match_operand:SI 1 "general_operand" "0")
-                (match_operand:SI 2 "general_operand" "dmsK")))
+                (match_operand:SI 2 "general_src_operand" "dmSTK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (umod:SI (match_dup 1) (match_dup 2)))]
   "TARGET_68020 && !TARGET_5200"
 (define_insn "divmodhi4"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (div:HI (match_operand:HI 1 "general_operand" "0")
-               (match_operand:HI 2 "general_operand" "dmsK")))
+               (match_operand:HI 2 "general_src_operand" "dmSKT")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (mod:HI (match_dup 1) (match_dup 2)))]
   "!TARGET_5200"
 (define_insn "udivmodhi4"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (udiv:HI (match_operand:HI 1 "general_operand" "0")
-                (match_operand:HI 2 "general_operand" "dmsK")))
+                (match_operand:HI 2 "general_src_operand" "dmSKT")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (umod:HI (match_dup 1) (match_dup 2)))]
   "!TARGET_5200"
   [(set (match_operand:DI 0 "general_operand" "=o,d")
        (and:DI (match_operand:DI 1 "general_operand" "%0,0")
                (match_operand:DI 2 "general_operand" "dn,don")))]
-  ""
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
   /* We can get CONST_DOUBLE, but also const1_rtx etc. */
-  if (GET_CODE (operands[2]) == CONST_DOUBLE
-     || GET_CODE (operands[2]) == CONST_INT)
+  if (CONSTANT_P (operands[2]))
     {
       rtx hi, lo;
 
-      if (GET_CODE (operands[2]) == CONST_DOUBLE)
-       {
-         hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
-         lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-       }
-      else
-       {
-         lo = operands[2];
-         hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
-       }
+      split_double (operands[2], &hi, &lo);
+
       switch (INTVAL (hi))
        {
          case 0 :
 ;; can't allocate pseudos into it.
 
 (define_expand "andsi3"
-  [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
-       (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+  [(set (match_operand:SI 0 "not_sp_operand" "")
+       (and:SI (match_operand:SI 1 "general_operand" "")
+               (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 (define_insn "andsi3_internal"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+               (match_operand:SI 2 "general_src_operand" "dKT,dmSM")))]
   "!TARGET_5200"
   "*
 {
 (define_insn "andsi3_5200"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "d,dmsK")))]
+               (match_operand:SI 2 "general_src_operand" "d,dmsK")))]
   "TARGET_5200"
   "and%.l %2,%0")
 
 (define_insn "andhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,d")
        (and:HI (match_operand:HI 1 "general_operand" "%0,0")
-               (match_operand:HI 2 "general_operand" "dn,dmn")))]
+               (match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (and:HI (match_dup 0)
-               (match_operand:HI 1 "general_operand" "dn,dmn")))]
+               (match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.w %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (and:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+       (and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "and%.w %1,%0")
 (define_insn "andqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (and:QI (match_operand:QI 1 "general_operand" "%0,0")
-               (match_operand:QI 2 "general_operand" "dn,dmn")))]
+               (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (and:QI (match_dup 0)
-               (match_operand:QI 1 "general_operand" "dn,dmn")))]
+               (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (and:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+       (and:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "and%.b %1,%0")
 
   CC_STATUS_INIT;
   if (GET_CODE (operands[0]) == REG)
-    operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+    operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   else
     operands[0] = adj_offsettable_operand (operands[0], 4);
   if (GET_MODE (operands[1]) == SImode)
 {
   CC_STATUS_INIT;
   /* We can get CONST_DOUBLE, but also const1_rtx etc. */
-  if (GET_CODE (operands[2]) == CONST_DOUBLE
-     || GET_CODE (operands[2]) == CONST_INT)
+  if (CONSTANT_P (operands[2]))
     {
       rtx hi, lo;
 
-      if (GET_CODE (operands[2]) == CONST_DOUBLE)
-       {
-         hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
-         lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-       }
-      else
-       {
-         lo = operands[2];
-         hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
-       }
+      split_double (operands[2], &hi, &lo);
+
       switch (INTVAL (hi))
        {
          case 0 :
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "general_operand" "")
        (ior:SI (match_operand:SI 1 "general_operand" "")
-               (match_operand:SI 2 "general_operand" "")))]
+               (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 (define_insn "iorsi3_internal"
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+                (match_operand:SI 2 "general_src_operand" "dKT,dmSMT")))]
   "! TARGET_5200"
   "*
 {
 (define_insn "iorsi3_5200"
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "d,dmsK")))]
+               (match_operand:SI 2 "general_src_operand" "d,dmsK")))]
   "TARGET_5200"
   "or%.l %2,%0")
 
 (define_insn "iorhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,d")
        (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
-               (match_operand:HI 2 "general_operand" "dn,dmn")))]
+               (match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (ior:HI (match_dup 0)
-               (match_operand:HI 1 "general_operand" "dn,dmn")))]
+               (match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.w %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (ior:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+       (ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "or%.w %1,%0")
 (define_insn "iorqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
-               (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (ior:QI (match_dup 0)
-               (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (ior:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+        (ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "or%.b %1,%0")
   [(set (match_operand:DI 0 "general_operand" "=od")
        (xor:DI (match_operand:DI 1 "general_operand" "%0")
                (match_operand:DI 2 "general_operand" "dn")))]
-  ""
+  "!TARGET_5200"
   "*
 {
   CC_STATUS_INIT;
   /* We can get CONST_DOUBLE, but also const1_rtx etc. */
-  if (GET_CODE (operands[2]) == CONST_DOUBLE
-     || GET_CODE (operands[2]) == CONST_INT)
+
+  if (CONSTANT_P (operands[2]))
     {
       rtx hi, lo;
 
-      if (GET_CODE (operands[2]) == CONST_DOUBLE)
-       {
-         hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
-         lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-       }
-      else
-       {
-         lo = operands[2];
-         hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
-       }
+      split_double (operands[2], &hi, &lo);
+
       switch (INTVAL (hi))
        {
          case 0 :
 (define_insn "xorsi3_internal"
   [(set (match_operand:SI 0 "general_operand" "=do,m")
        (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "di,dKs")))]
+                (match_operand:SI 2 "general_operand" "di,dKT")))]
+
   "!TARGET_5200"
   "*
 {
       target = operand_subword_force (operands[0], 0, SFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, SFmode),
-                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword (operands[0], 0, 1, DFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, DFmode),
-                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword_force (operands[0], 0, SFmode);
       result = expand_binop (SImode, and_optab,
                             operand_subword_force (operands[1], 0, SFmode),
-                            GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword (operands[0], 0, 1, DFmode);
       result = expand_binop (SImode, and_optab,
                             operand_subword_force (operands[1], 0, DFmode),
-                            GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
 (define_insn ""
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
                         (const_int 32)
-                        (match_operand:SI 2 "const_int_operand" "n"))
-       (match_operand:SI 3 "general_operand" "rmi"))]
+                        (match_operand:SI 1 "const_int_operand" "n"))
+       (match_operand:SI 2 "general_src_operand" "rmSi"))]
   "TARGET_68020 && TARGET_BITFIELD
-   && (INTVAL (operands[2]) % 8) == 0
+   && (INTVAL (operands[1]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[0], 0))"
   "*
 {
   operands[0]
-    = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+    = adj_offsettable_operand (operands[0], INTVAL (operands[1]) / 8);
 
-  return \"move%.l %3,%0\";
+  return \"move%.l %2,%0\";
 }")
 
 (define_insn ""
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
+       (zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
                         (const_int 32)
-                        (match_operand:SI 3 "const_int_operand" "n")))]
+                        (match_operand:SI 2 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
-   && (INTVAL (operands[3]) % 8) == 0
+   && (INTVAL (operands[2]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[1], 0))"
   "*
 {
   operands[1]
-    = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+    = adj_offsettable_operand (operands[1], INTVAL (operands[2]) / 8);
 
   return \"move%.l %1,%0\";
 }")
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+       (sign_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
                         (const_int 32)
-                        (match_operand:SI 3 "const_int_operand" "n")))]
+                        (match_operand:SI 2 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
-   && (INTVAL (operands[3]) % 8) == 0
+   && (INTVAL (operands[2]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[1], 0))"
   "*
 {
   operands[1]
-    = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+    = adj_offsettable_operand (operands[1], INTVAL (operands[2]) / 8);
 
   return \"move%.l %1,%0\";
 }")
       int width = GET_CODE (operands[0]) == REG ? 31 : 7;
       return output_btst (operands,
                          GEN_INT (width - INTVAL (operands[2])),
-                         operands[0],
-                         insn, 1000);
+                         operands[0], insn, 1000);
       /* Pass 1000 as SIGNPOS argument so that btst will
          not think we are testing the sign bit for an `and'
         and assume that nonzero implies a negative result.  */
       && GET_CODE (operands[2]) == CONST_INT)
     {
       int width = GET_CODE (operands[0]) == REG ? 31 : 7;
-      return output_btst (operands,
-                         GEN_INT (width - INTVAL (operands[2])),
-                         operands[0],
-                         insn, 1000);
+      return output_btst (operands, GEN_INT (width - INTVAL (operands[2])),
+                         operands[0], insn, 1000);
       /* Pass 1000 as SIGNPOS argument so that btst will
          not think we are testing the sign bit for an `and'
         and assume that nonzero implies a negative result.  */
   return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
 } ")
 
+;; Note that operand 0 of an SCC insn is supported in the hardware as
+;; memory, but we cannot allow it to be in memory in case the address
+;; needs to be reloaded.
+
 (define_expand "seq"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (eq:QI (cc0) (const_int 0)))]
   ""
   "
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (eq:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "*
-  cc_status = cc_prev_status;
-  OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
-")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (eq:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
+  ""
   "*
   cc_status = cc_prev_status;
   OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
 ")
 
 (define_expand "sne"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (ne:QI (cc0) (const_int 0)))]
   ""
   "
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (ne:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "*
-  cc_status = cc_prev_status;
-  OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
-")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (ne:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
+  ""
   "*
   cc_status = cc_prev_status;
   OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
 ")
 
 (define_expand "sgt"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (gt:QI (cc0) (const_int 0)))]
   ""
   "
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (gt:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "*
-  cc_status = cc_prev_status;
-  OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0);
-")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (gt:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
+  ""
   "*
   cc_status = cc_prev_status;
   OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0);
 ")
 
 (define_expand "sgtu"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (gtu:QI (cc0) (const_int 0)))]
   ""
   "")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (gtu:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"shi %0\"; ")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (gtu:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"shi %0\"; ")
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"shi %0\"; ")
 
 (define_expand "slt"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (lt:QI (cc0) (const_int 0)))]
   ""
   "
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (lt:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "* cc_status = cc_prev_status;
-     OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (lt:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
-  "* cc_status = cc_prev_status;
-     OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
+  ""
+  "*
+   cc_status = cc_prev_status;
+   OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
 
 (define_expand "sltu"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (ltu:QI (cc0) (const_int 0)))]
   ""
   "")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (ltu:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"scs %0\"; ")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (ltu:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"scs %0\"; ")
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"scs %0\"; ")
 
 (define_expand "sge"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (ge:QI (cc0) (const_int 0)))]
   ""
   "
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (ge:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "* cc_status = cc_prev_status;
-     OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (ge:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
-  "* cc_status = cc_prev_status;
-     OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+  ""
+  "*
+   cc_status = cc_prev_status;
+   OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
 
 (define_expand "sgeu"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (geu:QI (cc0) (const_int 0)))]
   ""
   "")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (geu:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"scc %0\"; ")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (geu:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"scc %0\"; ")
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"scc %0\"; ")
 
 (define_expand "sle"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (le:QI (cc0) (const_int 0)))]
   ""
   "
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (le:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "*
-  cc_status = cc_prev_status;
-  OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0);
-")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (le:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
+  ""
   "*
   cc_status = cc_prev_status;
   OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0);
 ")
 
 (define_expand "sleu"
-  [(set (match_operand:QI 0 "general_operand" "")
+  [(set (match_operand:QI 0 "register_operand" "")
        (leu:QI (cc0) (const_int 0)))]
   ""
   "")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=dm")
-       (leu:QI (cc0) (const_int 0)))]
-  "! TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"sls %0\"; ")
-
-(define_insn ""
-  [(set (match_operand:QI 0 "general_operand" "=d")
+  [(set (match_operand:QI 0 "register_operand" "=d")
        (leu:QI (cc0) (const_int 0)))]
-  "TARGET_5200"
-  "* cc_status = cc_prev_status;
-     return \"sls %0\"; ")
+  ""
+  "*
+   cc_status = cc_prev_status;
+   return \"sls %0\"; ")
 \f
 ;; Basic conditional jump instructions.
 
   "*
   if (GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+    {
+      if (TARGET_PCREL) return \"bsr.l %o0\";
 #ifdef MOTOROLA
 #ifdef HPUX_ASM
-    return \"bsr.l %0\";
+      return \"bsr.l %0\";
 #else
 #ifdef USE_GAS
-    return \"bsr.l %0@PLTPC\";
+      return \"bsr.l %0@PLTPC\";
 #else
-    return \"bsr %0@PLTPC\";
+      return \"bsr %0@PLTPC\";
 #endif
 #endif
 #else
-    /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
-       GAS just plain ignores it.  */
-    return \"jbsr %0,a1\";
+#ifdef USE_GAS
+      return \"bsr.l %0\";
+#else
+      /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
+        GAS just plain ignores it.  FIXME: not anymore, gas doesnt!  */
+      return \"jbsr %0,a1\";
+#endif
 #endif
+    }
   return \"jsr %0\";
 ")
 
   if (GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
     {
+      if (TARGET_PCREL) return \"bsr.l %o1\";
 #ifdef MOTOROLA
 #ifdef HPUX_ASM
       return \"bsr.l %1\";
 #endif
 #endif
 #else
+#ifdef USE_GAS
+      return \"bsr.l %1\";
+#else
       /* The ',a1' is a dummy argument telling the Sun assembler we want PIC
-         GAS just plain ignores it.  */
+         GAS just plain ignores it.  FIXME: Not anymore, gas doesnt!  */
       return \"jbsr %1,a1\";
 #endif
+#endif
     }
   return \"jsr %1\";
 ")
 {
   int i;
 
-  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
  "NEED_PROBE"
  "*
 {
-  operands[0] = gen_rtx_PLUS (SImode, stack_pointer_rtx,
-                             GEN_INT (NEED_PROBE));
+  operands[0] = plus_constant (stack_pointer_rtx, NEED_PROBE);
   return \"tstl %a0\";
 }")
 
 
   xoperands[1] = operands[1];
   xoperands[2]
-    = gen_rtx_MEM (QImode,
-                  gen_rtx_PLUS (VOIDmode, stack_pointer_rtx,
-                                GEN_INT (3)));
+    = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, 3));
   xoperands[3] = stack_pointer_rtx;
   if (!TARGET_5200)
     output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
 
 (define_insn "extendsfxf2"
   [(set (match_operand:XF 0 "general_operand" "=fm,f")
-       (float_extend:XF (match_operand:SF 1 "general_operand" "f,m")))]
+       (float_extend:XF (match_operand:SF 1 "general_operand" "f,rmF")))]
   "TARGET_68881"
   "*
 {
       return \"f%$move%.x %1,%0\";
     }
   if (FP_REG_P (operands[0]))
-    return \"f%$move%.s %f1,%0\";
+    {
+      if (FP_REG_P (operands[1]))
+       return \"f%$move%.x %1,%0\";
+      else if (ADDRESS_REG_P (operands[1]))
+       return \"move%.l %1,%-\;f%$move%.s %+,%0\";
+      else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_single (operands);
+      return \"f%$move%.s %f1,%0\";
+    }
   return \"fmove%.x %f1,%0\";
 }")
 
 (define_insn "extenddfxf2"
   [(set (match_operand:XF 0 "general_operand" "=fm,f")
        (float_extend:XF
-          (match_operand:DF 1 "general_operand" "f,m")))]
+          (match_operand:DF 1 "general_operand" "f,rmE")))]
   "TARGET_68881"
   "*
 {
       return \"fmove%.x %1,%0\";
     }
   if (FP_REG_P (operands[0]))
-    return \"f%&move%.d %f1,%0\";
+    {
+      if (REG_P (operands[1]))
+       {
+         rtx xoperands[2];
+         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+         output_asm_insn (\"move%.l %1,%-\", xoperands);
+         output_asm_insn (\"move%.l %1,%-\", operands);
+         return \"f%&move%.d %+,%0\";
+       }
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_double (operands);
+      return \"f%&move%.d %f1,%0\";
+    }
   return \"fmove%.x %f1,%0\";
 }")
 
       target = operand_subword (operands[0], 0, 1, XFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, XFmode),
-                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword (operands[0], 0, 1, XFmode);
       result = expand_binop (SImode, and_optab,
                             operand_subword_force (operands[1], 0, XFmode),
-                            GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
        (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
   "TARGET_68881 && flag_fast_math"
   "fcos%.x %1,%0")
+
+(define_insn "trap"
+  [(trap_if (const_int -1) (const_int 7))]
+  ""
+  "trap %#7")
+
+(define_insn "conditional_trap"
+  [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
+                           [(cc0) (const_int 0)])
+           (match_operand:SI 1 "const_int_operand" "I"))]
+  "TARGET_68020 && ! flags_in_68881 ()"
+  "*
+{
+  switch (GET_CODE (operands[0]))
+  {
+  case EQ:  return \"trapeq\";
+  case NE:  return \"trapne\";
+  case GT:  return \"trapgt\";
+  case GTU: return \"traphi\";
+  case LT:  return \"traplt\";
+  case LTU: return \"trapcs\";
+  case GE:  return \"trapge\";
+  case GEU: return \"trapcc\";
+  case LE:  return \"traple\";
+  case LEU: return \"trapls\";
+  default: abort();
+  }
+}")