constraints.md: Allow post_inc operand for "Ya" constraint.
authorJozef Lawrynowicz <jozef.l@mittosystems.com>
Tue, 15 Oct 2019 12:14:55 +0000 (12:14 +0000)
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>
Tue, 15 Oct 2019 12:14:55 +0000 (12:14 +0000)
2019-10-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* config/msp430/constraints.md: Allow post_inc operand for "Ya"
constraint.
* config/msp430/msp430.c (msp430_legitimate_address_p): Handle
POST_INC.
(msp430_subreg): Likewise.
(msp430_split_addsi): Likewise.
(msp430_print_operand_addr): Likewise.
* config/msp430/msp430.h (HAVE_POST_INCREMENT): Define.
(USE_STORE_POST_INCREMENT): Define.
* config/msp430/msp430.md: Use the msp430_general_dst_operand or
msp430_general_dst_nonv_operand predicates for the lvalues of insns.
* config/msp430/predicates.md (msp430_nonpostinc_operand): New.
(msp430_general_dst_operand): New.
(msp430_general_dst_nonv_operand): New.
(msp430_nonsubreg_operand): Remove.
(msp430_nonsubreg_dst_operand): New.
(msp430_nonsubreg_or_imm_operand): Allow reg or mem operands in place
of defunct msp430_nonsubreg_operand.
(msp430_nonsubregnonpostinc_or_imm_operand): New.

From-SVN: r276995

gcc/ChangeLog
gcc/config/msp430/constraints.md
gcc/config/msp430/msp430.c
gcc/config/msp430/msp430.h
gcc/config/msp430/msp430.md
gcc/config/msp430/predicates.md

index 09723d9d9529b213cadc18e39d27632ed9a4232e..767dc025e95167d999ac5fe6831321bbf070d058 100644 (file)
@@ -1,3 +1,25 @@
+2019-10-15  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * config/msp430/constraints.md: Allow post_inc operand for "Ya"
+       constraint.
+       * config/msp430/msp430.c (msp430_legitimate_address_p): Handle
+       POST_INC.
+       (msp430_subreg): Likewise.
+       (msp430_split_addsi): Likewise.
+       (msp430_print_operand_addr): Likewise.
+       * config/msp430/msp430.h (HAVE_POST_INCREMENT): Define.
+       (USE_STORE_POST_INCREMENT): Define.
+       * config/msp430/msp430.md: Use the msp430_general_dst_operand or
+       msp430_general_dst_nonv_operand predicates for the lvalues of insns.
+       * config/msp430/predicates.md (msp430_nonpostinc_operand): New.
+       (msp430_general_dst_operand): New.
+       (msp430_general_dst_nonv_operand): New.
+       (msp430_nonsubreg_operand): Remove.
+       (msp430_nonsubreg_dst_operand): New.
+       (msp430_nonsubreg_or_imm_operand): Allow reg or mem operands in place
+       of defunct msp430_nonsubreg_operand.
+       (msp430_nonsubregnonpostinc_or_imm_operand): New.
+
 2019-10-15  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/91929
index 4422b2b6454560deba17edbed3edc0dffb94bd7d..d01bcf9a242ba54b56a3355538b46cf7851c8d87 100644 (file)
@@ -60,6 +60,7 @@
                 (match_code "reg" "00")
                 (match_test ("CONST_INT_P (XEXP (XEXP (op, 0), 1))")))
            (match_test "CONSTANT_P (XEXP (op, 0))")
+           (match_code "post_inc" "0")
            )))
 
 (define_constraint "Yl"
index ae763faada3d744097eafbba61b2486551fe62e9..31029395c3de11e7f9a8441c535f0831c66df9b7 100644 (file)
@@ -942,12 +942,17 @@ msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
       return false;
 
     case PLUS:
+    case POST_INC:
       if (REG_P (XEXP (x, 0)))
        {
          if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
            return false;
          if (!reg_ok_for_addr (XEXP (x, 0), strict))
            return false;
+         if (GET_CODE (x) == POST_INC)
+           /* At this point, if the original rtx was a post_inc, we don't have
+              anything further to check.  */
+           return true;
          switch (GET_CODE (XEXP (x, 1)))
            {
            case CONST:
@@ -2810,6 +2815,7 @@ rtx
 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
 {
   rtx rv;
+  gcc_assert (mode == HImode);
 
   if (GET_CODE (r) == SUBREG
       && SUBREG_BYTE (r) == 0)
@@ -2826,7 +2832,15 @@ msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
        rv = simplify_gen_subreg (mode, ireg, imode, byte);
     }
   else if (GET_CODE (r) == MEM)
-    rv = adjust_address (r, mode, byte);
+    {
+      /* When byte == 2, we can be certain that we were already called with an
+        identical rtx with byte == 0.  So we don't need to do anything to
+        get a 2 byte offset of a (mem (post_inc)) rtx, since the address has
+        already been offset by the post_inc itself.  */
+      if (GET_CODE (XEXP (r, 0)) == POST_INC && byte == 2)
+       byte = 0;
+      rv = adjust_address (r, mode, byte);
+    }
   else if (GET_CODE (r) == SYMBOL_REF
           && (byte == 0 || byte == 2)
           && mode == HImode)
@@ -2861,6 +2875,18 @@ msp430_split_addsi (rtx *operands)
 
   if (GET_CODE (operands[5]) == CONST_INT)
     operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff);
+  /* Handle post_inc, for example:
+     (set (reg:SI)
+         (plus:SI (reg:SI)
+                  (mem:SI (post_inc:PSI (reg:PSI))))).  */
+  else if (MEM_P (operands[5]) && GET_CODE (XEXP (operands[5], 0)) == POST_INC)
+    {
+      /* Strip out the post_inc from (mem (post_inc (reg))).  */
+      operands[9] = XEXP (XEXP (operands[5], 0), 0);
+      operands[9] = gen_rtx_MEM (HImode, operands[9]);
+      /* Then zero extend as normal.  */
+      operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[9]);
+    }
   else
     operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]);
   return 0;
@@ -3205,6 +3231,10 @@ msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
       fprintf (file, "@");
       break;
 
+    case POST_INC:
+      fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);
+      return;
+
     case CONST:
     case CONST_INT:
     case SYMBOL_REF:
index f885de2bb2face2a266072c5fc6e5cf14ee27da2..73afe2e2d169cc89d4f4ce7ebbe7daeb1fea6814 100644 (file)
@@ -478,6 +478,18 @@ typedef struct
 
 #define ACCUMULATE_OUTGOING_ARGS 1
 
+#define HAVE_POST_INCREMENT 1
+
+/* This (unsurprisingly) improves code size in the vast majority of cases, we
+   want to prevent any instructions using a "store post increment" from being
+   generated.  These will have to later be reloaded since msp430 does not
+   support post inc for the destination operand.  */
+#define USE_STORE_POST_INCREMENT(MODE)  0
+
+/* Many other targets set USE_LOAD_POST_INCREMENT to 0.  For msp430-elf
+   the benefit of disabling it is not clear.  When looking at code size, on
+   average, there is a slight advantage to leaving it enabled.  */
+
 #undef  ASM_DECLARE_FUNCTION_NAME
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
   msp430_start_function ((FILE), (NAME), (DECL))
index ebd9c85fbb6ff5399a6858ac15f853d567933051..a533efa165683331b20f8e37834c66fc343f91e3 100644 (file)
 )
 
 (define_insn "movqi_topbyte"
-  [(set (match_operand:QI 0 "msp430_nonimmediate_operand" "=r")
+  [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r")
        (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
   "msp430x"
   "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
 )
 
 (define_insn "movqi"
-  [(set (match_operand:QI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+  [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
        (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))]
   ""
   "@
 )
 
 (define_insn "movhi"
-  [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=r,rYsYx,rm")
+  [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
        (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))]
   ""
   "@
 )
 
 (define_expand "movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand")
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
        (match_operand:SI 1 "general_operand"))]
   ""
   ""
   )
 
 (define_insn_and_split "movsi_s"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
        (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
   ""
   ""
   "reload_completed"
-  [(set (match_operand:HI 2 "nonimmediate_operand")
+  [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
        (match_operand:HI 4 "general_operand"))
-   (set (match_operand:HI 3 "nonimmediate_operand")
+   (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
        (match_operand:HI 5 "general_operand"))]
   "msp430_split_movsi (operands);"
   )
 
 (define_insn_and_split "movsi_x"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
        (match_operand:SI 1 "general_operand" "rmi"))]
   ""
   "#"
   "reload_completed"
-  [(set (match_operand:HI 2 "nonimmediate_operand")
+  [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
        (match_operand:HI 4 "general_operand"))
-   (set (match_operand:HI 3 "nonimmediate_operand")
+   (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
        (match_operand:HI 5 "general_operand"))]
   "msp430_split_movsi (operands);"
 )
 
 ;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
 (define_insn "movpsi"
-  [(set (match_operand:PSI 0 "msp430_nonimmediate_operand" "=r,r,r,Ya,rm")
+  [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,r,Ya,rm")
        (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))]
   ""
   "@
 ;; Math
 
 (define_insn "addpsi3"
-  [(set (match_operand:PSI          0 "msp430_nonimmediate_operand" "=r,rm")
-       (plus:PSI (match_operand:PSI 1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:PSI          0 "msp430_general_dst_operand" "=r,rm")
+       (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0")
                  (match_operand:PSI 2 "msp430_general_operand"      "rLs,rmi")))]
   ""
   "@
 )
 
 (define_insn "addqi3"
-  [(set (match_operand:QI         0 "msp430_nonimmediate_operand" "=rYsYx,rm")
-       (plus:QI (match_operand:QI 1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:QI         0 "msp430_general_dst_operand" "=rYsYx,rm")
+       (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0")
                 (match_operand:QI 2 "msp430_general_operand"      "riYsYx,rmi")))]
   ""
   "@
 )
 
 (define_insn "addhi3"
-  [(set (match_operand:HI          0 "msp430_nonimmediate_operand" "=rYsYx,rm")
-       (plus:HI (match_operand:HI  1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:HI          0 "msp430_general_dst_operand" "=rYsYx,rm")
+       (plus:HI (match_operand:HI  1 "msp430_general_operand" "%0,0")
                  (match_operand:HI 2 "msp430_general_operand"      "riYsYx,rmi")))]
   ""
   "@
 )
 
 (define_insn "addsi3"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=&rYsYx,rm")
-       (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm")
+       (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
                 (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
   ""
   "@
 ; increased register pressure.  Or possibly reload does not handle ADD patterns
 ; that are not single_set() very well.
 
+; match_operand 3 is likely to be the same as op2 most of the time - except
+; when op2 is a post_inc and we have stripped the post_inc from match_operand 3
+
 (define_insn "addhi3_cy"
-  [(set (match_operand:HI         0 "msp430_nonimmediate_operand" "=rYsYx,rm")
-       (plus:HI (match_operand:HI 1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:HI         0 "msp430_general_dst_operand" "=rYsYx,rm")
+       (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
                 (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm")))
    (set (reg:BI CARRY)
        (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
-                                          (zero_extend:SI (match_dup 2)))
+                                          (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm")))
                                  (const_int 16))))
    ]
   ""
   )
 
 (define_insn "addhi3_cy_i"
-  [(set (match_operand:HI          0 "nonimmediate_operand" "=r,rm")
-       (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
+  [(set (match_operand:HI         0 "msp430_general_dst_nonv_operand" "=r,rm")
+       (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
                 (match_operand:HI 2 "immediate_operand"     "i,i")))
    (set (reg:BI CARRY)
        (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
 
 ; Version of addhi that adds the carry, for SImode adds.
 (define_insn "addchi4_cy"
-  [(set (match_operand:HI                  0 "msp430_nonimmediate_operand" "=rYsYx,rm")
-       (plus:HI (plus:HI (match_operand:HI 1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:HI                  0 "msp430_general_dst_operand" "=rYsYx,rm")
+       (plus:HI (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
                          (match_operand:HI 2 "msp430_general_operand"      "riYsYx,rmi"))
                 (zero_extend:HI (reg:BI CARRY))))
    ]
 ; Split an SImode add into two HImode adds, keeping track of the carry
 ; so that gcc knows when it can and can't optimize away the two
 ; halves.
+; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to
+; enforce the position of a post_inc into op2 if present
 (define_split
-  [(set (match_operand:SI          0 "msp430_nonsubreg_operand")
-       (plus:SI (match_operand:SI 1 "msp430_nonsubreg_operand")
+  [(set (match_operand:SI         0 "msp430_nonsubreg_dst_operand")
+       (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand")
                 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
    ]
   ""
-  [(parallel [(set (match_operand:HI 3 "nonimmediate_operand" "=&rm")
+  [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm")
                   (plus:HI (match_dup 4)
                            (match_dup 5)))
              (set (reg:BI CARRY)
                                                      (match_dup 9))
                                             (const_int 16))))
              ])
-   (set (match_operand:HI 6 "nonimmediate_operand" "=&rm")
+   (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm")
        (plus:HI (plus:HI (match_dup 7)
                          (match_dup 8))
                 (zero_extend:HI (reg:BI CARRY))))
 
 ;; Alternatives 2 and 3 are to handle cases generated by reload.
 (define_insn "subpsi3"
-  [(set (match_operand:PSI            0 "nonimmediate_operand" "=r,   rm, &?r, ?&r")
-       (minus:PSI (match_operand:PSI 1 "general_operand"       "0,   0,   !r,  !i")
-                  (match_operand:PSI 2 "general_operand"       "rLs, rmi, rmi,  r")))]
+  [(set (match_operand:PSI           0 "msp430_general_dst_nonv_operand"       "=r,   rm, &?r, ?&r")
+       (minus:PSI (match_operand:PSI 1 "general_operand"                       "0,   0,   !r,  !i")
+                  (match_operand:PSI 2 "general_operand"                       "rLs, rmi, rmi,  r")))]
   ""
   "@
   SUBA\t%2, %0
 
 ;; Alternatives 2 and 3 are to handle cases generated by reload.
 (define_insn "subqi3"
-  [(set (match_operand:QI           0 "nonimmediate_operand" "=rYsYx,  rm,  &?r, ?&r")
+  [(set (match_operand:QI          0 "msp430_general_dst_nonv_operand" "=rYsYx,  rm,  &?r, ?&r")
        (minus:QI (match_operand:QI 1 "general_operand"       "0,    0,    !r,  !i")
                  (match_operand:QI 2 "general_operand"      " riYsYx, rmi, rmi,   r")))]
   ""
 
 ;; Alternatives 2 and 3 are to handle cases generated by reload.
 (define_insn "subhi3"
-  [(set (match_operand:HI           0 "nonimmediate_operand" "=rYsYx,  rm,  &?r, ?&r")
+  [(set (match_operand:HI          0 "msp430_general_dst_nonv_operand" "=rYsYx,  rm,  &?r, ?&r")
        (minus:HI (match_operand:HI 1 "general_operand"       "0,    0,    !r,  !i")
                  (match_operand:HI 2 "general_operand"      " riYsYx, rmi, rmi,   r")))]
   ""
 )
 
 (define_insn "subsi3"
-  [(set (match_operand:SI           0 "nonimmediate_operand" "=&rYsYx,m")
-       (minus:SI (match_operand:SI 1 "nonimmediate_operand"   "0,0")
+  [(set (match_operand:SI          0 "msp430_general_dst_nonv_operand" "=&rYsYx,m")
+       (minus:SI (match_operand:SI 1 "general_operand"   "0,0")
                  (match_operand:SI 2 "general_operand"        "riYsYx,mi")))]
   ""
   "@
 )
 
 (define_insn "*bic<mode>_cg"
-  [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=rYs,m")
+  [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
        (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")
                 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
   ""
 )
 
 (define_insn "bic<mode>3"
-  [(set (match_operand:QHI                  0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+  [(set (match_operand:QHI                  0 "msp430_general_dst_operand" "=rYsYx,rm")
        (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand"       "rYsYx,rmn"))
-                (match_operand:QHI          2 "msp430_nonimmediate_operand"  "0,0")))]
+                (match_operand:QHI          2 "msp430_general_operand"  "0,0")))]
   ""
   "@
    BIC%x0%b0\t%1, %0
 )
 
 (define_insn "and<mode>3"
-  [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=r,rYsYx,rm")
-       (and:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "%0,0,0")
+  [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
+       (and:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0,0")
                 (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))]
   ""
   "@
 )
 
 (define_insn "ior<mode>3"
-  [(set (match_operand:QHI         0 "msp430_nonimmediate_operand" "=rYsYx,rm")
-       (ior:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:QHI         0 "msp430_general_dst_operand" "=rYsYx,rm")
+       (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
                 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
   ""
   "@
 )
 
 (define_insn "xor<mode>3"
-  [(set (match_operand:QHI         0 "msp430_nonimmediate_operand" "=rYsYx,rm")
-       (xor:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "%0,0")
+  [(set (match_operand:QHI         0 "msp430_general_dst_operand" "=rYsYx,rm")
+       (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
                 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
   ""
   "@
 
 ;; Macro : XOR #~0, %0
 (define_insn "one_cmpl<mode>2"
-  [(set (match_operand:QHI         0 "msp430_nonimmediate_operand" "=rYs,m")
-       (not:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "0,0")))]
+  [(set (match_operand:QHI         0 "msp430_general_dst_operand" "=rYs,m")
+       (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))]
   ""
   "@
    INV%x0%b0\t%0
 )
 
 (define_insn "extendqihi2"
-  [(set (match_operand:HI                0 "msp430_nonimmediate_operand" "=rYs,m")
-       (sign_extend:HI (match_operand:QI 1 "msp430_nonimmediate_operand" "0,0")))]
+  [(set (match_operand:HI                0 "msp430_general_dst_operand" "=rYs,m")
+       (sign_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,0")))]
   ""
   "@
    SXT%X0\t%0
 )
 
 (define_insn "zero_extendqihi2"
-  [(set (match_operand:HI                0 "msp430_nonimmediate_operand" "=rYs,r,r,m")
-       (zero_extend:HI (match_operand:QI 1 "msp430_nonimmediate_operand" "0,rYs,m,0")))]
+  [(set (match_operand:HI                0 "msp430_general_dst_operand" "=rYs,r,r,m")
+       (zero_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,rYs,m,0")))]
   ""
   "@
    AND\t#0xff, %0
 )
 
 (define_insn "zero_extendhipsi2"
-  [(set (match_operand:PSI                0 "msp430_nonimmediate_operand" "=r,m")
-       (zero_extend:PSI (match_operand:HI 1 "msp430_nonimmediate_operand" "rm,r")))]
+  [(set (match_operand:PSI                0 "msp430_general_dst_operand" "=r,m")
+       (zero_extend:PSI (match_operand:HI 1 "msp430_general_operand" "rm,r")))]
   ""
   "@
   MOVX\t%1, %0
 )
 
 (define_insn "truncpsihi2"
-  [(set (match_operand:HI              0 "msp430_nonimmediate_operand" "=rm")
+  [(set (match_operand:HI              0 "msp430_general_dst_operand" "=rm")
        (truncate:HI (match_operand:PSI 1 "register_operand"      "r")))]
   ""
   "MOVX\t%1, %0"
 )
 
 (define_insn "extendhisi2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
   ""
   { return msp430x_extendhisi (operands); }
 )
 
 (define_insn "extendhipsi2"
-  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
-       (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))]
+  [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r")
+       (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))]
   "msp430x"
   "RLAM.A #4, %0 { RRAM.A #4, %0"
 )
 ;; paths.
 
 (define_insn "zero_extendqisi2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
   ""
   "MOV%X1.B\t%1,%L0 { CLR\t%H0"
 )
 
 (define_insn "zero_extendhisi2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
-       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")))]
+  [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm,r")
+       (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")))]
   ""
   "@
   MOV%X0.W\t#0,%H0
 )
 
 (define_insn "zero_extendhisipsi2"
-  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
-       (subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))]
+  [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r,r")
+       (subreg:PSI (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")) 0))]
   "msp430x"
   "@
    AND.W\t#-1,%0
 )
 
 (define_insn "extend_and_shift1_hipsi2"
-  [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
-       (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
+  [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
+       (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
                   (const_int 1)))]
   "msp430x"
   "RLAM.A #4, %0 { RRAM.A #3, %0"
 )
 
 (define_insn "extend_and_shift2_hipsi2"
-  [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
-       (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
+  [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
+       (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
                   (const_int 2)))]
   "msp430x"
   "RLAM.A #4, %0 { RRAM.A #2, %0"
 ;; signed A << C
 
 (define_expand "ashlhi3"
-  [(set (match_operand:HI            0 "nonimmediate_operand")
+  [(set (match_operand:HI           0 "msp430_general_dst_nonv_operand")
        (ashift:HI (match_operand:HI 1 "general_operand")
                   (match_operand:HI 2 "general_operand")))]
   ""
 )
 
 (define_insn "slli_1"
-  [(set (match_operand:HI            0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:HI           0 "msp430_general_dst_nonv_operand" "=rm")
        (ashift:HI (match_operand:HI 1 "general_operand"       "0")
                   (const_int 1)))]
   ""
 )
 
 (define_insn "slll_1"
-  [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI           0 "msp430_general_dst_nonv_operand" "=rm")
        (ashift:SI (match_operand:SI 1 "general_operand"       "0")
                   (const_int 1)))]
   ""
 )
 
 (define_insn "slll_2"
-  [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI           0 "msp430_general_dst_nonv_operand" "=rm")
        (ashift:SI (match_operand:SI 1 "general_operand"       "0")
                   (const_int 2)))]
   ""
 )
 
 (define_expand "ashlsi3"
-  [(set (match_operand:SI            0 "nonimmediate_operand")
+  [(set (match_operand:SI           0 "msp430_general_dst_nonv_operand")
        (ashift:SI (match_operand:SI 1 "general_operand")
                   (match_operand:SI 2 "general_operand")))]
   ""
 )
 
 (define_expand "ashldi3"
-  [(set (match_operand:DI           0 "nonimmediate_operand")
+  [(set (match_operand:DI           0 "msp430_general_dst_nonv_operand")
        (ashift:DI (match_operand:DI 1 "general_operand")
                   (match_operand:DI 2 "general_operand")))]
   ""
 ;; signed A >> C
 
 (define_expand "ashrhi3"
-  [(set (match_operand:HI              0 "nonimmediate_operand")
+  [(set (match_operand:HI             0 "msp430_general_dst_nonv_operand")
        (ashiftrt:HI (match_operand:HI 1 "general_operand")
                     (match_operand:HI 2 "general_operand")))]
   ""
 )
 
 (define_insn "srai_1"
-  [(set (match_operand:HI             0 "msp430_nonimmediate_operand" "=rm")
+  [(set (match_operand:HI             0 "msp430_general_dst_operand" "=rm")
        (ashiftrt:HI (match_operand:HI 1 "msp430_general_operand"      "0")
                     (const_int 1)))]
   ""
 )
 
 (define_insn "sral_1"
-  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI             0 "msp430_general_dst_nonv_operand" "=rm")
        (ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
                     (const_int 1)))]
   ""
 )
 
 (define_insn "sral_2"
-  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI             0 "msp430_general_dst_nonv_operand" "=rm")
        (ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
                     (const_int 2)))]
   ""
 )
 
 (define_expand "ashrsi3"
-  [(set (match_operand:SI              0 "nonimmediate_operand")
+  [(set (match_operand:SI             0 "msp430_general_dst_nonv_operand")
        (ashiftrt:SI (match_operand:SI 1 "general_operand")
                     (match_operand:SI 2 "general_operand")))]
   ""
 )
 
 (define_expand "ashrdi3"
-  [(set (match_operand:DI           0 "nonimmediate_operand")
+  [(set (match_operand:DI           0 "msp430_general_dst_nonv_operand")
        (ashift:DI (match_operand:DI 1 "general_operand")
                   (match_operand:DI 2 "general_operand")))]
   ""
 ;; unsigned A >> C
 
 (define_expand "lshrhi3"
-  [(set (match_operand:HI              0 "nonimmediate_operand")
+  [(set (match_operand:HI             0 "msp430_general_dst_nonv_operand")
        (lshiftrt:HI (match_operand:HI 1 "general_operand")
                     (match_operand:HI 2 "general_operand")))]
   ""
 )
 
 (define_insn "srli_1"
-  [(set (match_operand:HI              0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:HI             0 "msp430_general_dst_nonv_operand" "=rm")
        (lshiftrt:HI (match_operand:HI 1 "general_operand"       "0")
                     (const_int 1)))]
   ""
 )
 
 (define_insn "srll_1"
-  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
+  [(set (match_operand:SI             0 "msp430_general_dst_nonv_operand" "=rm")
        (lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
                     (const_int 1)))]
   ""
 )
 
 (define_insn "srll_2x"
-  [(set (match_operand:SI              0 "nonimmediate_operand" "=r")
+  [(set (match_operand:SI             0 "msp430_general_dst_nonv_operand" "=r")
        (lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
                     (const_int 2)))]
   "msp430x"
 )
 
 (define_expand "lshrsi3"
-  [(set (match_operand:SI              0 "nonimmediate_operand")
+  [(set (match_operand:SI             0 "msp430_general_dst_nonv_operand")
        (lshiftrt:SI (match_operand:SI 1 "general_operand")
                     (match_operand:SI 2 "general_operand")))]
   ""
 )
 
 (define_expand "lshrdi3"
-  [(set (match_operand:DI           0 "nonimmediate_operand")
+  [(set (match_operand:DI           0 "msp430_general_dst_nonv_operand")
        (ashift:DI (match_operand:DI 1 "general_operand")
                   (match_operand:DI 2 "general_operand")))]
   ""
 
 (define_insn "*bitbranch<mode>4"
   [(set (pc) (if_then_else
-             (ne (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+             (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
                           (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
                  (const_int 0))
               (label_ref (match_operand 2 "" ""))
 
 (define_insn "*bitbranch<mode>4"
   [(set (pc) (if_then_else
-             (eq (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+             (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
                           (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
                  (const_int 0))
               (label_ref (match_operand 2 "" ""))
 
 (define_insn "*bitbranch<mode>4"
   [(set (pc) (if_then_else
-             (eq (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+             (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
                           (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
                  (const_int 0))
               (pc)
 
 (define_insn "*bitbranch<mode>4"
   [(set (pc) (if_then_else
-             (ne (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+             (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
                           (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
                  (const_int 0))
               (pc)
 
 (define_insn "*bitbranch<mode>4_z"
   [(set (pc) (if_then_else
-             (ne (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYs,rm")
+             (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm")
                                    (const_int 1)
                                    (match_operand 1 "msp430_bitpos" "i,i"))
                  (const_int 0))
 
 (define_insn "*bitbranch<mode>4_z"
   [(set (pc) (if_then_else
-             (eq (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rm")
+             (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
                                   (const_int 1)
                                   (match_operand 1 "msp430_bitpos" "i"))
                  (const_int 0))
 
 (define_insn "*bitbranch<mode>4_z"
   [(set (pc) (if_then_else
-             (eq (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rm")
+             (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
                                   (const_int 1)
                                   (match_operand 1 "msp430_bitpos" "i"))
                  (const_int 0))
 
 (define_insn "*bitbranch<mode>4_z"
   [(set (pc) (if_then_else
-             (ne (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rm")
+             (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
                                   (const_int 1)
                                   (match_operand 1 "msp430_bitpos" "i"))
                  (const_int 0))
index 751548c4ae889c2fde3e864f46f8c9f19093a74b..d8cdaba381367d712b79e20b83c4e4c51e5fb5f4 100644 (file)
        (match_test ("memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0), MEM_ADDR_SPACE (op))")))
 )
 
+; TRUE if neither op nor op0 are a post_inc.  We cannot use post_inc for the
+; dst operand so this must be used for any predicates which might allow a mem.
+; Since we check both op and op0, this will be FALSE for both "(post_inc)" and
+; "(mem (post_inc))"
+(define_predicate "msp430_nonpostinc_operand"
+  (not (ior (match_code "post_inc")
+           (and (ior (match_operand 0 "msp430_volatile_memory_operand")
+                     (match_code "mem"))
+                (match_code "post_inc" "0")))))
+
 ; TRUE for any valid general operand.  We do this because
 ; general_operand refuses to match volatile memory refs.
-
 (define_predicate "msp430_general_operand"
   (ior (match_operand 0 "general_operand")
        (match_operand 0 "msp430_volatile_memory_operand"))
 )
 
 ; Likewise for nonimmediate_operand.
-
 (define_predicate "msp430_nonimmediate_operand"
   (ior (match_operand 0 "nonimmediate_operand")
        (match_operand 0 "msp430_volatile_memory_operand"))
 )
 
+; Similar to msp430_nonimmediate_operand but disallow post_inc operands
+(define_predicate "msp430_general_dst_operand"
+  (and (match_operand 0 "msp430_nonpostinc_operand")
+       (match_operand 0 "msp430_nonimmediate_operand")))
+
+; Similar to msp430_general_dst_operand but disallow volatile memory references
+; Note that msp430_nonpostinc_operand will allow a volatile mem but nonimmediate
+; will not, so overall this predicate will behave as expected.
+; The heuristic for deciding if we can allow volatile memory appears to be:
+;   "If the number of references to the variable in the source code matches
+;    the number of references to the variable in the assembly template, we can
+;    safely allow a volatile memory reference".
+;      - paraphrasing DJ Delorie here:
+;       https://gcc.gnu.org/ml/gcc-patches/2014-05/msg00870.html
+; When applied to instruction patterns, this means that we can only allow
+; volatile memory when the output assembler template contains only one
+; instruction which references that volatile address.
+(define_predicate "msp430_general_dst_nonv_operand"
+  (and (match_operand 0 "msp430_nonpostinc_operand")
+       (match_operand 0 "nonimmediate_operand")))
+
 (define_predicate "ubyte_operand"
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), 0, 255)")))
                     || INTVAL (op) == ~8
                     || INTVAL (op) == ~(-1) "))))
 
-(define_predicate "msp430_nonsubreg_operand"
-  (match_code "reg,mem"))
+; See above note on post_inc
+(define_predicate "msp430_nonsubreg_dst_operand"
+  (and (match_operand 0 "msp430_nonpostinc_operand")
+       (match_code "reg,mem")))
 
 (define_predicate "msp430_nonsubreg_or_imm_operand"
-  (ior (match_operand 0 "msp430_nonsubreg_operand")
+  (ior (match_code "reg,mem")
        (match_operand 0 "immediate_operand")))
 
+(define_predicate "msp430_nonsubregnonpostinc_or_imm_operand"
+  (and (match_operand 0 "msp430_nonpostinc_operand")
+       (ior (match_code "reg,mem")
+           (match_operand 0 "immediate_operand"))))
+
 ; TRUE for constants which are bit positions for zero_extract
 (define_predicate "msp430_bitpos"
   (and (match_code "const_int")