diff gcc/config/mn10300/mn10300.md @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/config/mn10300/mn10300.md	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/config/mn10300/mn10300.md	Fri Oct 27 22:46:09 2017 +0900
@@ -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-2017 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")
@@ -61,15 +61,15 @@
          (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))
@@ -239,8 +239,8 @@
 })
 
 (define_insn "*movqi_internal"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
-	(match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m,*z,d")
+	(match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D,d,*z"))]
   "(register_operand (operands[0], QImode)
     || register_operand (operands[1], QImode))"
 {
@@ -250,6 +250,8 @@
       return "";
     case 1:
     case 2:
+    case 5:
+    case 6:
       return "mov %1,%0";
     case 3:
     case 4:
@@ -266,6 +268,8 @@
 			(const_int 13) (const_int 24))
 	  (if_then_else (eq_attr "cpu" "am34")
 			(const_int 11) (const_int 22))
+	  (const_int 11)
+	  (const_int 11)
 	 ])]
 )
 
@@ -283,8 +287,8 @@
 })
 
 (define_insn "*movhi_internal"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
-	(match_operand:HI 1 "general_operand"      "  0,  i,D*r,m,D"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m,*z,d")
+	(match_operand:HI 1 "general_operand"      "  0,  i,D*r,m,D,d,*z"))]
   "(register_operand (operands[0], HImode)
     || register_operand (operands[1], HImode))"
 {
@@ -302,6 +306,8 @@
 	  && REGNO_EXTENDED_P (REGNO (operands[0]), 1))
 	return "movu %1,%0";
       /* FALLTHRU */
+    case 5:
+    case 6:
     case 2:
       return "mov %1,%0";
     case 3:
@@ -320,6 +326,10 @@
 	  		(const_int 13) (const_int 24))
 	  (if_then_else (eq_attr "cpu" "am34")
 	  		(const_int 11) (const_int 22))
+	  (if_then_else (eq_attr "cpu" "am34")
+	  		(const_int 11) (const_int 22))
+	  (if_then_else (eq_attr "cpu" "am34")
+	  		(const_int 11) (const_int 22))
 	 ])]
 )
 
@@ -491,8 +501,8 @@
 })
 
 (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))"
@@ -505,6 +515,8 @@
     case 3:
     case 7:
     case 8:
+    case 11:
+    case 12:
       return "mov %1,%0";
     case 2:
     case 4:
@@ -537,6 +549,8 @@
 				(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)
 		 ])]
 )
 
@@ -578,12 +592,12 @@
 
 ;; 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")]
@@ -591,12 +605,12 @@
 
 ;; A helper to expand the above, with the CC_MODE filled in.
 (define_expand "addsi3_flags"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
+  [(parallel [(set (reg:CCZNC CC_REG)
+		   (compare:CCZNC (plus:SI (match_dup 1) (match_dup 2))
+				  (const_int 0)))
+	      (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)
-		   (compare:CCZNC (plus:SI (match_dup 1) (match_dup 2))
-				  (const_int 0)))])]
+			    (match_operand:SI 2 "nonmemory_operand")))])]
   ""
 )
 
@@ -777,12 +791,12 @@
 )
 
 (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
@@ -793,12 +807,12 @@
 
 ;; A helper to expand the above, with the CC_MODE filled in.
 (define_expand "subsi3_flags"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
+  [(parallel [(set (reg:CCZNC CC_REG)
+		   (compare:CCZNC (minus:SI (match_dup 1) (match_dup 2))
+				  (const_int 0)))
+	      (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)
-		   (compare:CCZNC (minus:SI (match_dup 1) (match_dup 2))
-				  (const_int 0)))])]
+			     (match_operand:SI 2 "nonmemory_operand")))])]
   ""
 )
 
@@ -983,7 +997,7 @@
 ;; ??? 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...
 
@@ -1181,12 +1195,12 @@
 )
 
 (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
@@ -1268,12 +1282,12 @@
 )
 
 (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
@@ -1304,12 +1318,12 @@
 )
 
 (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
@@ -1332,11 +1346,11 @@
 )
 
 (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"
 )
@@ -1375,7 +1389,7 @@
   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")))]
@@ -1792,13 +1806,27 @@
 )
 
 ;; ----------------------------------------------------------------------
-;; 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"
 )
@@ -1810,7 +1838,7 @@
 		   UNSPEC_BSCH))
    (clobber (reg:CC CC_REG))]
   "TARGET_AM33"
-  "bsch %1,%0"
+  "bsch %1, %0"
 )
 
 ;; ----------------------------------------------------------------------
@@ -2018,7 +2046,7 @@
 {
   /* 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 "";
 })
@@ -2031,8 +2059,7 @@
 {
   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 "";
 }
@@ -2152,3 +2179,39 @@
   [(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)))]
+)