]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/mn10300/mn10300.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / mn10300 / mn10300.md
index f3f23e7fa3770fafb61b138edc3634ba66780baa..e1a016bb9e98124f688a5446a89e24faa1c08cf2 100644 (file)
@@ -1,7 +1,5 @@
 ;; GCC machine description for Matsushita MN10300
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1996-2020 Free Software Foundation, Inc.
 ;; Contributed by Jeff Law (law@cygnus.com).
 
 ;; This file is part of GCC.
@@ -42,6 +40,8 @@
 
   ;; This is used to encode LIW patterns.
   (UNSPEC_LIW          8)
+  ;; This is for the low overhead loop instructions.
+  (UNSPEC_SETLB         9)
 ])
 
 (include "predicates.md")
          (const_int 1)
 
          (and (eq_attr "isa" "am33")
-             (ne (symbol_ref "TARGET_AM33") (const_int 0)))
+             (match_test "TARGET_AM33"))
          (const_int 1)
 
          (and (eq_attr "isa" "am33_2")
-             (ne (symbol_ref "TARGET_AM33_2") (const_int 0)))
+             (match_test "TARGET_AM33_2"))
          (const_int 1)
         
          (and (eq_attr "isa" "am34")
-             (ne (symbol_ref "TARGET_AM34") (const_int 0)))
+             (match_test "TARGET_AM34"))
          (const_int 1)
        ]
        (const_int 0))
 })
 
 (define_insn "*movsf_internal"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q")
-       (match_operand:SF 1 "general_operand"      "  0,F,F,r,f,f,r,m,r,Q,f"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q,z,d")
+       (match_operand:SF 1 "general_operand"      "  0,F,F,r,f,f,r,m,r,Q,f,d,z"))]
   "TARGET_AM33_2
    && (register_operand (operands[0], SFmode)
        || register_operand (operands[1], SFmode))"
     case 3:
     case 7:
     case 8:
+    case 11:
+    case 12:
       return "mov %1,%0";
     case 2:
     case 4:
                                (const_int 13) (const_int 24))
                  (if_then_else (eq_attr "cpu" "am34")
                                (const_int 13) (const_int 24))
+                 (const_int 22)
+                 (const_int 22)
                 ])]
 )
 
 
 ;; Note that ADD IMM,SP does not set the flags, so omit that here.
 (define_insn "*addsi3_flags"
-  [(set (match_operand:SI          0 "register_operand"  "=r,!r")
-       (plus:SI (match_operand:SI 1 "register_operand"  "%0, r")
-                (match_operand:SI 2 "nonmemory_operand" "ri, r")))
-   (set (reg CC_REG)
-       (compare (plus:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (plus:SI (match_operand:SI 1 "register_operand"  "%0, r")
+                         (match_operand:SI 2 "nonmemory_operand" "ri, r"))
+                (const_int 0)))
+   (set (match_operand:SI          0 "register_operand"  "=r,!r")
+       (plus:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
   { return mn10300_output_add (operands, true); }
   [(set_attr "timings" "11,22")]
 
 ;; A helper to expand the above, with the CC_MODE filled in.
 (define_expand "addsi3_flags"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (plus:SI (match_operand:SI 1 "register_operand")
-                           (match_operand:SI 2 "nonmemory_operand")))
-             (set (reg:CCZNC CC_REG)
+  [(parallel [(set (reg:CCZNC CC_REG)
                   (compare:CCZNC (plus:SI (match_dup 1) (match_dup 2))
-                                 (const_int 0)))])]
+                                 (const_int 0)))
+             (set (match_operand:SI 0 "register_operand")
+                  (plus:SI (match_operand:SI 1 "register_operand")
+                           (match_operand:SI 2 "nonmemory_operand")))])]
   ""
 )
 
   rtx scratch = NULL_RTX;
   if (!rtx_equal_p (operands[0], operands[2]))
     {
-      gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[1]));
       if (reg_overlap_mentioned_p (operands[0], operands[3])
          || reg_overlap_mentioned_p (operands[0], operands[4]))
        {
 )
 
 (define_insn "*subsi3_flags"
-  [(set (match_operand:SI           0 "register_operand"  "=r, r")
-       (minus:SI (match_operand:SI 1 "register_operand"   "0, r")
-                 (match_operand:SI 2 "nonmemory_operand"  "ri,r")))
-   (set (reg CC_REG)
-       (compare (minus:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (minus:SI (match_operand:SI 1 "register_operand"  "0, r")
+                          (match_operand:SI 2 "nonmemory_operand" "ri,r"))
+                (const_int 0)))
+   (set (match_operand:SI           0 "register_operand"  "=r, r")
+       (minus:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
   "@
    sub %2,%0
 
 ;; A helper to expand the above, with the CC_MODE filled in.
 (define_expand "subsi3_flags"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (minus:SI (match_operand:SI 1 "register_operand")
-                            (match_operand:SI 2 "nonmemory_operand")))
-             (set (reg:CCZNC CC_REG)
+  [(parallel [(set (reg:CCZNC CC_REG)
                   (compare:CCZNC (minus:SI (match_dup 1) (match_dup 2))
-                                 (const_int 0)))])]
+                                 (const_int 0)))
+             (set (match_operand:SI 0 "register_operand")
+                  (minus:SI (match_operand:SI 1 "register_operand")
+                            (match_operand:SI 2 "nonmemory_operand")))])]
   ""
 )
 
 ;; ??? Note that AM33 has a third multiply variant that puts the high part
 ;; into the MDRQ register, however this variant also constrains the inputs
 ;; to be in DATA_REGS and thus isn't as helpful as it might be considering
-;; the existance of the 4-operand multiply.  Nor is there a set of divide
+;; the existence of the 4-operand multiply.  Nor is there a set of divide
 ;; insns that use MDRQ.  Given that there is an IMM->MDRQ insn, this would
 ;; have been very handy for starting udivmodsi4...
 
 )
 
 (define_insn "*andsi3_flags"
-  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
-       (and:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
-               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
-   (set (reg CC_REG)
-       (compare (and:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (and:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+                        (match_operand:SI 2 "nonmemory_operand" " i,D,r"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (and:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "@
    and %2,%0
 )
 
 (define_insn "*iorsi3_flags"
-  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
-       (ior:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
-               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
-   (set (reg CC_REG)
-       (compare (ior:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (ior:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+                        (match_operand:SI 2 "nonmemory_operand" " i,D,r"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (ior:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "@
    or %2,%0
 )
 
 (define_insn "*xorsi3_flags"
-  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
-       (xor:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
-               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
-   (set (reg CC_REG)
-       (compare (xor:SI (match_dup 1) (match_dup 2))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (xor:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+                        (match_operand:SI 2 "nonmemory_operand" " i,D,r"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (xor:SI (match_dup 1) (match_dup 2)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "@
    xor %2,%0
 )
 
 (define_insn "*one_cmplsi2_flags"
-  [(set (match_operand:SI         0 "register_operand" "=D")
-       (not:SI (match_operand:SI 1 "register_operand" " 0")))
-   (set (reg CC_REG)
-       (compare (not:SI (match_dup 1))
-                (const_int 0)))]
+  [(set (reg CC_REG)
+       (compare (not:SI (match_operand:SI 1 "register_operand" "0"))
+                (const_int 0)))
+   (set (match_operand:SI         0 "register_operand" "=D")
+       (not:SI (match_dup 1)))]
   "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "not %0"
 )
   DONE;
 })
 
-(define_insn "*cmpsi"
+(define_insn "cmpsi"
   [(set (reg CC_REG)
        (compare (match_operand:SI 0 "register_operand"  "r,r,r")
                 (match_operand:SI 1 "nonmemory_operand" "r,O,i")))]
 )
 
 ;; ----------------------------------------------------------------------
-;; MISCELANEOUS
+;; MISCELLANEOUS
 ;; ----------------------------------------------------------------------
 
+;; Note the use of the (const_int 0) when generating the insn that matches
+;; the bsch pattern.  This ensures that the destination register is
+;; initialised with 0 which will make the BSCH instruction set searching
+;; at bit 31.
+;;
+;; The XOR in the instruction sequence below is there because the BSCH
+;; instruction returns the bit number of the highest set bit and we want
+;; the number of zero bits above that bit.  The AM33 does not have a
+;; reverse subtraction instruction, but we can use a simple xor instead
+;; since we know that the top 27 bits are clear.
 (define_expand "clzsi2"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (unspec:SI [(match_operand:SI 1 "register_operand" "")
+  [(parallel [(set (match_operand:SI 0 "register_operand")
+                  (unspec:SI [(match_operand:SI 1 "register_operand")
                               (const_int 0)] UNSPEC_BSCH))
+             (clobber (reg:CC CC_REG))])
+   (parallel [(set (match_dup 0)
+                  (xor:SI (match_dup 0)
+                          (const_int 31)))
              (clobber (reg:CC CC_REG))])]
   "TARGET_AM33"
 )
                   UNSPEC_BSCH))
    (clobber (reg:CC CC_REG))]
   "TARGET_AM33"
-  "bsch %1,%0"
+  "bsch %1, %0"
 )
 
 ;; ----------------------------------------------------------------------
 {
   /* The RETF insn is up to 3 cycles faster than RET.  */
   fputs ((mn10300_can_use_retf_insn () ? "\tretf " : "\tret "), asm_out_file);
-  mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
+  mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs (NULL));
   fprintf (asm_out_file, ",%d\n", (int) INTVAL (operands[0]));
   return "";
 })
 {
   fputs ("\tmovm ", asm_out_file);
   mn10300_print_reg_list (asm_out_file,
-                          mn10300_store_multiple_operation (operands[0],
-                                                           VOIDmode));
+                          mn10300_store_multiple_regs (operands[0]));
   fprintf (asm_out_file, ",(sp)\n");
   return "";
 }
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 13) (const_int 12)))]
 )
+
+;; Note - in theory the doloop patterns could be used here to express
+;; the SETLB and Lcc instructions.  In practice this does not work because
+;; the acceptable forms of the doloop patterns do not include UNSPECs
+;; and without them gcc's basic block reordering code can duplicate the
+;; doloop_end pattern, leading to bogus multiple decrements of the loop
+;; counter. 
+
+(define_insn "setlb"
+  [(unspec [(const_int 0)] UNSPEC_SETLB)]
+  "TARGET_AM33 && TARGET_ALLOW_SETLB"
+  "setlb"
+)
+
+(define_insn "Lcc"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                     [(reg:CC CC_REG) (const_int 0)])
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (unspec [(const_int 1)] UNSPEC_SETLB)]
+  "TARGET_AM33 && TARGET_ALLOW_SETLB"
+  "L%b0 # loop back to: %1"
+)
+
+(define_insn "FLcc"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                     [(reg:CC_FLOAT CC_REG) (const_int 0)])
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (unspec [(const_int 2)] UNSPEC_SETLB)]
+  "TARGET_AM33_2 && TARGET_ALLOW_SETLB"
+  "FL%b0 # loop back to: %1"
+  [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") (const_int 44) (const_int 11)))]
+)