]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/c6x/c6x.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / c6x / c6x.md
index 7935a8170599eacca250af7997f16dc4656cdc84..9ac101ac622ec3ae8d6e856f19a862bbfd8d3090 100644 (file)
@@ -1,5 +1,5 @@
 ;; Machine description for TI C6X.
-;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 ;; Contributed by Andrew Jenner <andrew@codesourcery.com>
 ;; Contributed by Bernd Schmidt <bernds@codesourcery.com>
 ;; Contributed by CodeSourcery.
   "n,y"
   (const_string "n"))
 
+;; This describes the relationship between operands and register files.
+;; For example, "sxs" means that operands 0 and 2 determine the side of
+;; the machine, and operand 1 can optionally use the cross path.  "dt" and
+;; "td" are used to describe loads and stores.
+;; Used for register renaming in loops for improving modulo scheduling.
+(define_attr "op_pattern"
+  "unknown,dt,td,sx,sxs,ssx"
+  (cond [(eq_attr "type" "load") (const_string "td")
+        (eq_attr "type" "store") (const_string "dt")]
+       (const_string "unknown")))
+
 (define_attr "has_shadow"
   "n,y"
   (const_string "n"))
         (eq_attr "type" "mpysp2dp") (const_int 5)]
        (const_int 1)))
 
+;; The number of cycles during which the instruction reserves functional
+;; units.
+(define_attr "reserve_cycles" ""
+  (cond [(eq_attr "type" "cmpdp") (const_int 2)
+        (eq_attr "type" "adddp") (const_int 2)
+        (eq_attr "type" "mpydp") (const_int 4)
+        (eq_attr "type" "mpyi") (const_int 4)
+        (eq_attr "type" "mpyid") (const_int 4)
+        (eq_attr "type" "mpyspdp") (const_int 2)]
+       (const_int 1)))
+
 (define_attr "predicable" "no,yes"
   (const_string "yes"))
 
        ]
        (const_string "unknown")))
 
-(define_automaton "c6x_1,c6x_w1,c6x_2,c6x_w2,c6x_m1,c6x_m2,c6x_t1,c6x_t2,c6x_branch")
+(define_automaton "c6x_1,c6x_2,c6x_m1,c6x_m2,c6x_t1,c6x_t2,c6x_branch")
+(automata_option "no-comb-vect")
 (automata_option "ndfa")
+(automata_option "collapse-ndfa")
 
-(define_cpu_unit "d1,l1,s1" "c6x_1")
+(define_query_cpu_unit "d1,l1,s1" "c6x_1")
 (define_cpu_unit "x1" "c6x_1")
-(define_cpu_unit "l1w,s1w" "c6x_w1")
-(define_cpu_unit "m1" "c6x_m1")
+(define_cpu_unit "l1w,s1w" "c6x_1")
+(define_query_cpu_unit "m1" "c6x_m1")
 (define_cpu_unit "m1w" "c6x_m1")
 (define_cpu_unit "t1" "c6x_t1")
-(define_cpu_unit "d2,l2,s2" "c6x_2")
+(define_query_cpu_unit "d2,l2,s2" "c6x_2")
 (define_cpu_unit "x2" "c6x_2")
-(define_cpu_unit "l2w,s2w" "c6x_w2")
-(define_cpu_unit "m2" "c6x_m2")
+(define_cpu_unit "l2w,s2w" "c6x_2")
+(define_query_cpu_unit "m2" "c6x_m2")
 (define_cpu_unit "m2w" "c6x_m2")
 (define_cpu_unit "t2" "c6x_t2")
+;; A special set of units used to identify specific reservations, rather than
+;; just units.
+(define_query_cpu_unit "fps1,fpl1,adddps1,adddpl1" "c6x_1")
+(define_query_cpu_unit "fps2,fpl2,adddps2,adddpl2" "c6x_2")
 
 ;; There can be up to two branches in one cycle (on the .s1 and .s2
 ;; units), but some instructions must not be scheduled in parallel
   "%|%.\\tldw\\t%$\\t*+%1[%2], %0"
   [(set_attr "type" "load")
    (set_attr "units" "d_addr")
+   (set_attr "op_pattern" "unknown")
    (set_attr "dest_regfile" "a,b")
    (set_attr "addr_regfile" "b")])
 
   [(set (match_dup 2) (match_dup 3))]
 {
   unsigned HOST_WIDE_INT mask, val;
-  enum machine_mode inner_mode = GET_MODE_INNER (<MODE>mode);
+  machine_mode inner_mode = GET_MODE_INNER (<MODE>mode);
   int i;
 
   val = 0;
   unsigned HOST_WIDE_INT mask;
   unsigned HOST_WIDE_INT val[2];
   rtx lo_half, hi_half;
-  enum machine_mode inner_mode = GET_MODE_INNER (<MODE>mode);
+  machine_mode inner_mode = GET_MODE_INNER (<MODE>mode);
   int i, j;
 
   split_di (operands, 1, &lo_half, &hi_half);
                              (ashift:SI (match_dup 4) (const_int 16))))]
 {
   long values;
-  REAL_VALUE_TYPE value;
 
   gcc_assert (GET_CODE (operands[1]) == CONST_DOUBLE);
 
-  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
-  REAL_VALUE_TO_TARGET_SINGLE (value, values);
+  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values);
 
   operands[2] = gen_rtx_REG (SImode, true_regnum (operands[0]));
   operands[3] = GEN_INT (trunc_int_for_mode (values, HImode));
    %|%.\\tadda%D2\\t%$\\t%1, %2, %0"
   [(set_attr "units" "d")
    (set_attr "cross" "y,n")
+   (set_attr "op_pattern" "unknown")
    (set_attr "predicable" "no")])
 
 ;; Move instruction patterns
   [(set_attr "type" "*,*,*,*,*,*,load,load,load,load,store,store,store,store")
    (set_attr "units62" "dls,dls,ls,ls,s,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
    (set_attr "units64" "dls,dls,ls,ls,dl,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
+   (set_attr "op_pattern" "sx,sx,sx,sx,*,*,*,*,*,*,*,*,*,*")
    (set_attr "addr_regfile" "*,*,*,*,*,*,a,b,b,a,a,b,b,a")
    (set_attr "dest_regfile" "*,*,*,*,*,*,a,a,b,b,a,a,b,b")
    (set_attr "cross" "n,n,y,y,n,n,n,y,n,y,n,y,n,y")])
   [(set_attr "type" "*,*,*,*,*,*,*,*,*,load,load,load,load,store,store,store,store")
    (set_attr "units62" "dls,dls,ls,ls,s,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
    (set_attr "units64" "dls,dls,ls,ls,dl,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
+   (set_attr "op_pattern" "sx,sx,sx,sx,*,*,*,*,*,*,*,*,*,*,*,*,*")
    (set_attr "addr_regfile" "*,*,*,*,*,*,*,*,*,a,b,b,a,a,b,b,a")
    (set_attr "dest_regfile" "*,*,*,*,*,*,*,*,*,a,a,b,b,a,a,b,b")
    (set_attr "cross" "n,n,y,y,n,n,y,n,*,n,y,n,y,n,y,n,y")
                       UNSPEC_MISALIGNED_ACCESS))]
   "TARGET_INSNS_64"
 {
-  if (memory_operand (operands[0], <MODE>mode))
+  if (MEM_P (operands[0]))
     {
       emit_insn (gen_movmisalign<mode>_store (operands[0], operands[1]));
       DONE;
 
 (define_insn "<ext_name><mode>si2"
  [(set (match_operand:SI 0 "register_operand" "=a,b,a,?a, b,?b")
-       (any_ext: SI (match_operand:QIHIM 1 "nonimmediate_operand" "a,b,Q, R, R, Q")))]
+       (any_ext:SI (match_operand:QIHIM 1 "nonimmediate_operand" "a,b,Q, R, R, Q")))]
   ""
  "@
   %|%.\\text<u>\\t%$\\t%1, <ext_shift>, <ext_shift>, %0
       rtx tmpreg = gen_reg_rtx (SImode);
       rtx t = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
                              SImode, operands[2], operands[3]);
-      emit_insn (gen_rtx_SET (VOIDmode, tmpreg, t));
+      emit_insn (gen_rtx_SET (tmpreg, t));
       emit_insn (gen_scmpsi_insn (operands[0],
                                  gen_rtx_fmt_ee (EQ, SImode, tmpreg, const0_rtx),
                                  tmpreg, const0_rtx));
   }"
 )
 
+;; -------------------------------------------------------------------------
+;; Doloop
+;; -------------------------------------------------------------------------
+
+; operand 0 is the loop count pseudo register
+; operand 1 is the label to jump to at the top of the loop
+(define_expand "doloop_end"
+  [(parallel [(set (pc) (if_then_else
+                         (ne (match_operand:SI 0 "" "")
+                             (const_int 1))
+                         (label_ref (match_operand 1 "" ""))
+                         (pc)))
+             (set (match_dup 0)
+                  (plus:SI (match_dup 0)
+                           (const_int -1)))
+             (clobber (match_dup 2))])] ; match_scratch
+  "TARGET_INSNS_64PLUS && optimize"
+{
+  /* The loop optimizer doesn't check the predicates... */
+  if (GET_MODE (operands[0]) != SImode)
+    FAIL;
+  operands[2] = gen_rtx_SCRATCH (SImode);
+})
+
+(define_insn "mvilc"
+  [(set (reg:SI REG_ILC)
+       (unspec [(match_operand:SI 0 "register_operand" "a,b")] UNSPEC_MVILC))]
+  "TARGET_INSNS_64PLUS"
+  "%|%.\\tmvc\\t%$\\t%0, ILC"
+  [(set_attr "predicable" "no")
+   (set_attr "cross" "y,n")
+   (set_attr "units" "s")
+   (set_attr "dest_regfile" "b")
+   (set_attr "type" "mvilc")])
+  
+(define_insn "sploop"
+  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")
+                    (reg:SI REG_ILC)]
+                   UNSPECV_SPLOOP)]
+  "TARGET_INSNS_64PLUS"
+  "%|%.\\tsploop\t%0"
+  [(set_attr "predicable" "no")
+   (set_attr "type" "sploop")])
+  
+(define_insn "spkernel"
+  [(set (pc)
+       (if_then_else
+        (ne (unspec_volatile:SI
+             [(match_operand:SI 0 "const_int_operand" "i")
+              (match_operand:SI 1 "const_int_operand" "i")]
+             UNSPECV_SPKERNEL)
+            (const_int 1))
+        (label_ref (match_operand 2 "" ""))
+        (pc)))]
+  "TARGET_INSNS_64PLUS"
+  "%|%.\\tspkernel\t%0, %1"
+  [(set_attr "predicable" "no")
+   (set_attr "type" "spkernel")])
+  
+(define_insn "loop_end"
+  [(set (pc)
+       (if_then_else (ne (match_operand:SI 3 "nonimmediate_operand" "0,0,0,*r")
+                         (const_int 1))
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (set (match_operand:SI 0 "nonimmediate_operand" "=AB,*r,m,m")
+       (plus:SI (match_dup 3)
+                (const_int -1)))
+   (clobber (match_scratch:SI 2 "=X,&AB,&AB,&AB"))]
+  "TARGET_INSNS_64PLUS && optimize"
+  "#"
+  [(set_attr "type" "spkernel")])
+
+(define_split
+  [(set (pc)
+       (if_then_else (ne (match_operand:SI 3 "nonimmediate_operand" "")
+                         (const_int 1))
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (set (match_operand:SI 0 "memory_operand" "")
+       (plus:SI (match_dup 3)
+                (const_int -1)))
+   (clobber (match_scratch 2))]
+  ""
+  [(set (match_dup 2) (plus:SI (match_dup 3) (const_int -1)))
+   (set (match_dup 0) (match_dup 2))
+   (set (pc)
+       (if_then_else (ne (match_dup 2) (const_int 0))
+                     (label_ref (match_dup 1))
+                     (pc)))]
+{
+  if (!REG_P (operands[3]))
+    {
+      emit_move_insn (operands[2], operands[3]);
+      operands[3] = operands[2];
+    }
+})
+
 ;; -------------------------------------------------------------------------
 ;; Delayed-branch real jumps and shadows
 ;; -------------------------------------------------------------------------
 
 (define_insn "real_jump"
-  [(unspec [(match_operand 0 "c6x_jump_operand" "a,b,s") (const_int 0)]
+  [(unspec [(match_operand 0 "c6x_jump_operand" "a,b,S3") (const_int 0)]
           UNSPEC_REAL_JUMP)]
   ""
 {
    (set_attr "cross" "y,n")
    (set_attr "dest_regfile" "b")])
 
+;; computed_jump_p returns true if it finds a constant; so use one in the
+;; unspec.
 (define_insn "indirect_jump_shadow"
-  [(set (pc) (unspec [(pc)] UNSPEC_JUMP_SHADOW))]
+  [(set (pc) (unspec [(const_int 1)] UNSPEC_JUMP_SHADOW))]
   ""
   ";; indirect jump occurs"
   [(set_attr "type" "shadow")])
 
 (define_expand "ctzdi2"
   [(set (match_operand:DI 0 "register_operand" "")
-       (ctz:SI (match_operand:DI 1 "register_operand" "")))]
+       (ctz:DI (match_operand:DI 1 "register_operand" "")))]
   "TARGET_INSNS_64"
 {
   rtx tmpreg = gen_reg_rtx (DImode);
   "TARGET_FP && flag_reciprocal_math"
 {
   operands[3] = force_reg (SFmode,
-                          CONST_DOUBLE_FROM_REAL_VALUE (dconst2, SFmode));
+                          const_double_from_real_value (dconst2, SFmode));
   operands[4] = gen_reg_rtx (SFmode);
   operands[5] = gen_reg_rtx (SFmode);
   operands[6] = gen_reg_rtx (SFmode);
   "TARGET_FP && flag_reciprocal_math"
 {
   operands[3] = force_reg (DFmode,
-                          CONST_DOUBLE_FROM_REAL_VALUE (dconst2, DFmode));
+                          const_double_from_real_value (dconst2, DFmode));
   operands[4] = gen_reg_rtx (DFmode);
   operands[5] = gen_reg_rtx (DFmode);
   operands[6] = gen_reg_rtx (DFmode);
 ;; Block moves
 ;; -------------------------------------------------------------------------
 
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
   [(use (match_operand:BLK 0 "memory_operand" ""))
    (use (match_operand:BLK 1 "memory_operand" ""))
    (use (match_operand:SI 2 "nonmemory_operand" ""))
    (use (match_operand:SI 5 "const_int_operand" ""))]
   ""
 {
- if (c6x_expand_movmem (operands[0], operands[1], operands[2], operands[3],
+ if (c6x_expand_cpymem (operands[0], operands[1], operands[2], operands[3],
                        operands[4], operands[5]))
    DONE;
  else