OSDN Git Service

(tstdi): Optimized for "d" case.
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Apr 1996 12:21:03 +0000 (12:21 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Apr 1996 12:21:03 +0000 (12:21 +0000)
(movqi): Allow moving "i" into "a".
(zero_extendsidi2): Alternatives merged.
(extendplussidi): Fixed when operands 0 and 1 share a register.
(adddi_sexthishl32): Constraints reordered for better reload.
(adddi3,subdi_sexthishl32,subdi3,negdi2): Likewise.
(ashldi_sexthi): Accept "m" as operand 0.
(ashldi_const32): Alternatives merged.
(ashift patterns): Output "lsl" instead of "asl".
(beq0_di): If condition codes already set, output only branch insn.
(bne0_di,bge0_di,blt0_di): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@11783 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/m68k/m68k.md

index 2919103..78deaf7 100644 (file)
@@ -37,7 +37,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
 ;;- 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 
+;;- 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.
+;;- fscale.  The TARGET_68060 flag turns the use of the opcodes off.
 
 ;;-            FPA port explanation:
 
 ;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
 ;; be folded while optimizing anyway.
 
-(define_expand "tstdi"
-  [(parallel
-    [(set (cc0)
-         (match_operand:DI 0 "nonimmediate_operand" "d"))
-     (clobber (match_dup 1))])]
-  ""
-  "operands[1] = gen_reg_rtx (DImode);")
-
-(define_insn ""
+(define_insn "tstdi"
   [(set (cc0)
-       (match_operand:DI 1 "nonimmediate_operand" "0"))
-   (clobber (match_operand:DI 0 "register_operand" "=d"))]
+       (match_operand:DI 0 "nonimmediate_operand" "am,d"))
+   (clobber (match_scratch:SI 1 "=X,d"))
+   (clobber (match_scratch:DI 2 "=d,X"))]
   ""
   "*
 {
-  cc_status.flags |= CC_REVERSED;
-  return \"neg%.l %R0\;negx%.l %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
+    /*
+    ** '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"
        (match_operand:QI 0 "nonimmediate_operand" "dm"))]
   ""
   "tst%.b %0")
-  
+
 (define_expand "tstsf"
   [(set (cc0)
        (match_operand:SF 0 "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 */
     {
       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);
     }
 ;; 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 "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.
+  ;; This isn't so on the 68010, but we have no TARGET_68010.
   "(TARGET_68020
     || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
   "*
   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 */
   "*
 {
   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)
          && (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.  */
+            This isn't so on the 68010, but we have no TARGET_68010.  */
          && (TARGET_68020
              || !(GET_CODE (operands[0]) == MEM
                   && MEM_VOLATILE_P (operands[0]))))
          && (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.  */
+            This isn't so on the 68010, but we have no TARGET_68010.  */
          && (TARGET_68020
              || !(GET_CODE (operands[0]) == MEM
                   && MEM_VOLATILE_P (operands[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"))]
+       (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi,?*a,m"))]
   ""
   "*
 {
       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)
     {
        {
          /* 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, 
+            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]))
            {
     }
 
   /* 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])))
+     This isn't so on the 68010, but we have no TARGET_68010.  */
+  if (!ADDRESS_REG_P (operands[0])
+      && (TARGET_68020
+         || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
     {
       if (operands[1] == const0_rtx)
        return \"clr%.b %0\";
 {
   if (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.  */
+         This isn't so on the 68010, but we have no TARGET_68010.  */
       && (TARGET_68020
           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
     return \"clr%.b %0\";
 
 ;; 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]))
       operands[1] = operands[2];
       operands[2] = tmp;
     }
+  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)
-    return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;extb%.l %0\";
+    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 "adddi_sexthishl32"
-  [(set (match_operand:DI 0 "general_operand" "=o,d,a")
+  [(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"))
+          (match_operand:HI 1 "general_operand" "rm,rm,rm,rm"))
             (const_int 32))
-        (match_operand:DI 2 "general_operand" "0,0,0")))
-   (clobber (match_scratch:SI 3 "=&d*a,a*d,X"))]
+        (match_operand:DI 2 "general_operand" "0,0,0,0")))
+   (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
   ""
   "*
 {
   CC_STATUS_INIT;
   if (ADDRESS_REG_P (operands[0]))
     return \"add%.w %1,%0\";
-  else if (DATA_REG_P (operands[3]))
-    return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%0\";
-  else if (DATA_REG_P (operands[0]))
+  else if (ADDRESS_REG_P (operands[3]))
     return \"move%.w %1,%3\;add%.l %3,%0\";
   else
-    return \"move%.l %0,%3\;add%.w %1,%3\;mov%.l %3,%0\";
+    return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%0\";
 } ")
 
 (define_insn "adddi_dilshr32"
 } ")
 
 (define_insn "adddi3"
-  [(set (match_operand:DI 0 "general_operand" "=d,<,d,o<>")
-       (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
-                (match_operand:DI 2 "general_operand" "d,<,*ao>,d")))
-   (clobber (match_scratch:SI 3 "=X,X,&d,&d"))]
+  [(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"))]
   ""
   "*
 {
       if (INTVAL (operands[2]) > 8
          && INTVAL (operands[2]) <= 16
          && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+         && 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) 
+         && TARGET_68020)
        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, 
+         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
          && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+         && 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) 
+         && TARGET_68020)
        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, 
+         operands[2] = gen_rtx (CONST_INT, VOIDmode,
                                 - INTVAL (operands[2]) - 8);
          return \"subq%.w %#8,%0\;subq%.w %2,%0\";
        }
       if (INTVAL (operands[1]) > 8
          && INTVAL (operands[1]) <= 16
          && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+         && 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) 
+         && TARGET_68020)
        {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, 
+         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
          && ADDRESS_REG_P (operands[0])
-         && TARGET_68020) 
+         && 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) 
+         && TARGET_68020)
        {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, 
+         operands[1] = gen_rtx (CONST_INT, VOIDmode,
                                 - INTVAL (operands[1]) - 8);
          return \"subq%.w %#8,%0\;subq%.w %1,%0\";
        }
 ;; subtract instructions
 
 (define_insn "subdi_sexthishl32"
-  [(set (match_operand:DI 0 "general_operand" "=o,d,a")
-    (minus:DI (match_operand:DI 1 "general_operand" "0,0,0")
-        (ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm"))
+  [(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 3 "=&d*a,a*d,X"))]
+   (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
   ""
   "*
 {
   CC_STATUS_INIT;
   if (ADDRESS_REG_P (operands[0]))
     return \"sub%.w %2,%0\";
-  else if (DATA_REG_P (operands[3]))
-    return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%0\";
-  else if (DATA_REG_P (operands[0]))
+  else if (ADDRESS_REG_P (operands[3]))
     return \"move%.w %2,%3\;sub%.l %3,%0\";
   else
-    return \"move%.l %0,%3\;sub%.w %2,%3\;mov%.l %3,%0\";
+    return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%0\";
 } ")
 
 (define_insn "subdi_dishl32"
 } ")
 
 (define_insn "subdi3"
-  [(set (match_operand:DI 0 "general_operand" "=d,<,d,o<>")
-       (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
-                (match_operand:DI 2 "general_operand" "d,<,*ao>,d")))
-   (clobber (match_scratch:SI 3 "=X,X,&d,&d"))]
+  [(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"))]
   ""
   "*
 {
       && (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);
       && 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);
   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.  */
 ;; negation instructions
 
 (define_insn "negdi2"
-  [(set (match_operand:DI 0 "general_operand" "=d*ao,<")
-       (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
+  [(set (match_operand:DI 0 "general_operand" "=<,do,!*a")
+       (neg:DI (match_operand:DI 1 "general_operand" "0,0,0")))]
   ""
   "*
 {
-  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);
 
       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 "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]))
   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 ""
   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"
        (ashift:HI (match_operand:HI 1 "register_operand" "0")
                   (match_operand:HI 2 "general_operand" "dI")))]
   ""
-  "asl%.w %2,%0")
+  "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")
+  "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")
+  "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")
+  "lsl%.b %1,%0")
 
 ;; On all 68k models, this makes faster code in a special case.
 
 {
   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)
 {
   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,
   ""
   "*
 {
+  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
             (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
   ""
   "*
 {
+  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 \"tst%.l %0\;jbge %l1\";
+         return \"jble %l1\";
 #else
-  return \"tst%.l %0\;jge %l1\";
+         return \"jle %l1\";
+#endif
+       }
+      else
+       {
+#ifdef MOTOROLA
+         return \"jbpl %l1\";
+#else
+         return \"jpl %l1\";
+#endif
+       }
+    }
+  CC_STATUS_INIT;
+#ifdef MOTOROLA
+  return \"tst%.l %0\;jbpl %l1\";
+#else
+  return \"tst%.l %0\;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;
 #ifdef MOTOROLA
   return \"tst%.l %0\;jbmi %l1\";
 #else
 
 
 ;; For PIC calls, in order to be able to support
-;; dynamic linker LAZY BINDING, all the procedure calls need to go 
+;; 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 
+;; 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.
 ;;
 ;; We have different patterns for PIC calls and non-PIC calls.  The
 ;; different patterns are only used to choose the right syntax.
 ;;
-;; 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 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"
   "*
-  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
   "*
 #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"
   "*
-  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
         output_asm_insn (\"addq%.w %1,%0\", xoperands);
       else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
        {
-         xoperands[1] = gen_rtx (CONST_INT, VOIDmode, 
+         xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
                                  INTVAL (xoperands[1]) - 8);
          output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
        }
         output_asm_insn (\"addq%.w %1,%0\", xoperands);
       else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
        {
-         xoperands[1] = gen_rtx (CONST_INT, VOIDmode, 
+         xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
                                  INTVAL (xoperands[1]) - 8);
          output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
        }
          && (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.  */
+            This isn't so on the 68010, but we have no TARGET_68010.  */
          && (TARGET_68020
              || !(GET_CODE (operands[0]) == MEM
                   && MEM_VOLATILE_P (operands[0]))))
     }
   return \"fmove%.d %f1,%0\";
 }")
+
 (define_insn "truncxfsf2"
   [(set (match_operand:SF 0 "general_operand" "=dm")
        (float_truncate:SF
 
       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),
 
       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),