[ARC] Add new ARCv2 instructions.
authorClaudiu Zissulescu <claziss@synopsys.com>
Mon, 2 May 2016 08:54:34 +0000 (10:54 +0200)
committerClaudiu Zissulescu <claziss@gcc.gnu.org>
Mon, 2 May 2016 08:54:34 +0000 (10:54 +0200)
gcc/
2016-05-02  Claudiu Zissulescu  <claziss@synopsys.com>

* config/arc/arc-protos.h (compact_memory_operand_p): Declare.
* config/arc/arc.c (arc_output_commutative_cond_exec): Consider
bmaskn instruction.
(arc_dwarf_register_span): Remove enum keyword.
(compact_memory_operand_p): New function.
* config/arc/arc.h (reg_class): Add code density register classes.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
* config/arc/arc.md (*movqi_insn): Add code density instructions.
(*movhi_insn, *movsi_insn, *movsf_insn): Likewise.
(*extendhisi2_i, andsi3_i, cmpsi_cc_insn_mixed): Likewise.
(*cmpsi_cc_c_insn, *movsi_ne): Likewise.
* config/arc/constraints.md (C2p, Uts, Cm1, Cm3, Ucd): New
constraints.
(h, Rcd, Rsd, Rzd): New register constraints.
(T): Use compact_memory_operand_p function.
* config/arc/predicates.md (compact_load_memory_operand): Remove.

From-SVN: r235707

gcc/ChangeLog
gcc/config/arc/arc-protos.h
gcc/config/arc/arc.c
gcc/config/arc/arc.h
gcc/config/arc/arc.md
gcc/config/arc/constraints.md
gcc/config/arc/predicates.md

index 0b4ab48fd9eff4f6abe770fe4bab2f15b95e3e19..fecfdab68becca0b2bdd0ca81fa5853c35d14e76 100644 (file)
@@ -1,3 +1,23 @@
+2016-05-02  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * config/arc/arc-protos.h (compact_memory_operand_p): Declare.
+       * config/arc/arc.c (arc_output_commutative_cond_exec): Consider
+       bmaskn instruction.
+       (arc_dwarf_register_span): Remove enum keyword.
+       (compact_memory_operand_p): New function.
+       * config/arc/arc.h (reg_class): Add code density register classes.
+       (REG_CLASS_NAMES): Likewise.
+       (REG_CLASS_CONTENTS): Likewise.
+       * config/arc/arc.md (*movqi_insn): Add code density instructions.
+       (*movhi_insn, *movsi_insn, *movsf_insn): Likewise.
+       (*extendhisi2_i, andsi3_i, cmpsi_cc_insn_mixed): Likewise.
+       (*cmpsi_cc_c_insn, *movsi_ne): Likewise.
+       * config/arc/constraints.md (C2p, Uts, Cm1, Cm3, Ucd): New
+       constraints.
+       (h, Rcd, Rsd, Rzd): New register constraints.
+       (T): Use compact_memory_operand_p function.
+       * config/arc/predicates.md (compact_load_memory_operand): Remove.
+
 2016-05-02  Oleg Endo  <olegendo@gcc.gnu.org>
 
        * config/sh/sh.md (*negnegt, *movtt): Remove.
index 3bf28a088bd936bdd43705099bee8fca74ae270c..8630e2d84daabd8d5fa0f6a190c2c5dd2a9b5463 100644 (file)
@@ -44,7 +44,7 @@ extern void emit_shift (enum rtx_code, rtx, rtx, rtx);
 extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
 extern void arc_split_compare_and_swap (rtx *);
 extern void arc_expand_compare_and_swap (rtx *);
-
+extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
index dfaea7b92412a5226df74959e885f393cf85821d..a54fddb45d329e3d098435ee3134a8642bc3913e 100644 (file)
@@ -7389,6 +7389,11 @@ arc_output_commutative_cond_exec (rtx *operands, bool output_p)
       case AND:
        if (satisfies_constraint_C1p (operands[2]))
          pat = "bmsk%? %0,%1,%Z2";
+       else if (satisfies_constraint_C2p (operands[2]))
+         {
+           operands[2] = GEN_INT ((~INTVAL (operands[2])));
+           pat = "bmskn%? %0,%1,%Z2";
+         }
        else if (satisfies_constraint_Ccp (operands[2]))
          pat = "bclr%? %0,%1,%M2";
        else if (satisfies_constraint_CnL (operands[2]))
@@ -9859,12 +9864,153 @@ arc_dwarf_register_span (rtx rtl)
 
 /* We can't inline this in INSN_REFERENCES_ARE_DELAYED because
    resource.h doesn't include the required header files.  */
+
 bool
 insn_is_tls_gd_dispatch (rtx_insn *insn)
 {
   return recog_memoized (insn) == CODE_FOR_tls_gd_dispatch;
 }
 
+/* Return true if OP is an acceptable memory operand for ARCompact
+   16-bit load instructions of MODE.
+
+   AV2SHORT: TRUE if address needs to fit into the new ARCv2 short
+   non scaled instructions.
+
+   SCALED: TRUE if address can be scaled.  */
+
+bool
+compact_memory_operand_p (rtx op, machine_mode mode,
+                         bool av2short, bool scaled)
+{
+  rtx addr, plus0, plus1;
+  int size, off;
+
+  /* Eliminate non-memory operations.  */
+  if (GET_CODE (op) != MEM)
+    return 0;
+
+  /* .di instructions have no 16-bit form.  */
+  if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
+    return false;
+
+  if (mode == VOIDmode)
+    mode = GET_MODE (op);
+
+  size = GET_MODE_SIZE (mode);
+
+  /* dword operations really put out 2 instructions, so eliminate
+     them.  */
+  if (size > UNITS_PER_WORD)
+    return false;
+
+  /* Decode the address now.  */
+  addr = XEXP (op, 0);
+  switch (GET_CODE (addr))
+    {
+    case REG:
+      return (REGNO (addr) >= FIRST_PSEUDO_REGISTER
+             || COMPACT_GP_REG_P (REGNO (addr))
+             || (SP_REG_P (REGNO (addr)) && (size != 2)));
+    case PLUS:
+      plus0 = XEXP (addr, 0);
+      plus1 = XEXP (addr, 1);
+
+      if ((GET_CODE (plus0) == REG)
+         && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+             || COMPACT_GP_REG_P (REGNO (plus0)))
+         && ((GET_CODE (plus1) == REG)
+             && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
+                 || COMPACT_GP_REG_P (REGNO (plus1)))))
+       {
+         return !av2short;
+       }
+
+      if ((GET_CODE (plus0) == REG)
+         && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+             || (COMPACT_GP_REG_P (REGNO (plus0)) && !av2short)
+             || (IN_RANGE (REGNO (plus0), 0, 31) && av2short))
+         && (GET_CODE (plus1) == CONST_INT))
+       {
+         bool valid = false;
+
+         off = INTVAL (plus1);
+
+         /* Negative offset is not supported in 16-bit load/store insns.  */
+         if (off < 0)
+           return 0;
+
+         /* Only u5 immediates allowed in code density instructions.  */
+         if (av2short)
+           {
+             switch (size)
+               {
+               case 1:
+                 return false;
+               case 2:
+                 /* This is an ldh_s.x instruction, check the u6
+                    immediate.  */
+                 if (COMPACT_GP_REG_P (REGNO (plus0)))
+                   valid = true;
+                 break;
+               case 4:
+                 /* Only u5 immediates allowed in 32bit access code
+                    density instructions.  */
+                 if (REGNO (plus0) <= 31)
+                   return ((off < 32) && (off % 4 == 0));
+                 break;
+               default:
+                 return false;
+               }
+           }
+         else
+           if (COMPACT_GP_REG_P (REGNO (plus0)))
+             valid = true;
+
+         if (valid)
+           {
+
+             switch (size)
+               {
+               case 1:
+                 return (off < 32);
+               case 2:
+                 /* The 6-bit constant get shifted to fit the real
+                    5-bits field.  Check also for the alignment.  */
+                 return ((off < 64) && (off % 2 == 0));
+               case 4:
+                 return ((off < 128) && (off % 4 == 0));
+               default:
+                 return false;
+               }
+           }
+       }
+
+      if (REG_P (plus0) && CONST_INT_P (plus1)
+         && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+             || SP_REG_P (REGNO (plus0)))
+         && !av2short)
+       {
+         off = INTVAL (plus1);
+         return ((size != 2) && (off >= 0 && off < 128) && (off % 4 == 0));
+       }
+
+      if ((GET_CODE (plus0) == MULT)
+         && (GET_CODE (XEXP (plus0, 0)) == REG)
+         && ((REGNO (XEXP (plus0, 0)) >= FIRST_PSEUDO_REGISTER)
+             || COMPACT_GP_REG_P (REGNO (XEXP (plus0, 0))))
+         && (GET_CODE (plus1) == REG)
+         && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
+             || COMPACT_GP_REG_P (REGNO (plus1))))
+       return scaled;
+    default:
+      break ;
+      /* TODO: 'gp' and 'pcl' are to supported as base address operand
+        for 16-bit load instructions.  */
+    }
+  return false;
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-arc.h"
index bc14d11ab1f9b98ad2fa51d99549b7de6282199e..f6b85ea7e51b19501c044b338a17b0d4cf8a03a5 100644 (file)
@@ -674,6 +674,9 @@ enum reg_class
    WRITABLE_CORE_REGS,         /* 'w' */
    CHEAP_CORE_REGS,            /* 'c' */
    ALL_CORE_REGS,              /* 'Rac' */
+   R0R3_CD_REGS,               /* 'Rcd' */
+   R0R1_CD_REGS,               /* 'Rsd' */
+   AC16_H_REGS,                        /* 'h' */
    ALL_REGS,
    LIM_REG_CLASSES
 };
@@ -700,6 +703,9 @@ enum reg_class
   "MPY_WRITABLE_CORE_REGS",   \
   "WRITABLE_CORE_REGS",   \
   "CHEAP_CORE_REGS",     \
+  "R0R3_CD_REGS", \
+  "R0R1_CD_REGS", \
+  "AC16_H_REGS",           \
   "ALL_CORE_REGS",       \
   "ALL_REGS"             \
 }
@@ -732,6 +738,9 @@ enum reg_class
   {0xffffffff, 0xd0000000, 0x00000000, 0x00000000, 0x00000000},      /* 'w', r0-r31, r60 */ \
   {0xffffffff, 0xdfffffff, 0x00000000, 0x00000000, 0x00000000},      /* 'c', r0-r60, ap, pcl */ \
   {0xffffffff, 0xdfffffff, 0x00000000, 0x00000000, 0x00000000},      /* 'Rac', r0-r60, ap, pcl */ \
+  {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rcd', r0-r3 */ \
+  {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rsd', r0-r1 */ \
+  {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'h',  r0-28, r30 */ \
   {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff}       /* All Registers */               \
 }
 
index c61107f4b41628d9b0e8885646c310b0d1cb6a0c..85e54587d99df9866a0f5396deccee22fde237ff 100644 (file)
 ; The iscompact attribute allows the epilogue expander to know for which
 ; insns it should lengthen the return insn.
 (define_insn "*movqi_insn"
-  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,w,Rcq,S,!*x,r,r,Ucm,m,???m")
-       (match_operand:QI 1 "move_src_operand"  "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
+  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,???w, w,Rcq,  S,!*x,  r,r, Ucm,m,???m")
+       (match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hCm1,cL,I,?Rac,?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
   "register_operand (operands[0], QImode)
    || register_operand (operands[1], QImode)"
   "@
    mov%? %0,%1%&
    mov%? %0,%1%&
    mov%? %0,%1%&
+   mov%? %0,%1%&
    mov%? %0,%1
    mov%? %0,%1
    mov%? %0,%1
    xstb%U0 %1,%0
    stb%U0%V0 %1,%0
    stb%U0%V0 %1,%0"
-  [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false,false,false")
-   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no,no,no")
-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*")])
+  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
+   (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,false,true,true,true,false,false,false,false,false")
+   (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,no,no,no,no,no,no,no,no")
+   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*")])
 
 (define_expand "movhi"
   [(set (match_operand:HI 0 "move_dest_operand" "")
   "if (prepare_move_operands (operands, HImode)) DONE;")
 
 (define_insn "*movhi_insn"
-  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,Rcq#q,w,Rcq,S,r,r,Ucm,m,???m,VUsc")
-       (match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,?i,T,Rcq,Ucm,m,?Rac,c,?Rac,i"))]
+  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,???w,Rcq#q, w,Rcq,  S,  r,r, Ucm,m,???m,VUsc,VUsc")
+       (match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,hCm1,cL,I,?Rac,   ?i,?i,  T,Rcq,Ucm,m,?Rac,c,?Rac, Cm3,i"))]
   "register_operand (operands[0], HImode)
    || register_operand (operands[1], HImode)
    || (CONSTANT_P (operands[1])
    mov%? %0,%1%&
    mov%? %0,%1%&
    mov%? %0,%1%&
+   mov%? %0,%1%&
    mov%? %0,%1
    mov%? %0,%1
    mov%? %0,%1
    xst%_%U0 %1,%0
    st%_%U0%V0 %1,%0
    st%_%U0%V0 %1,%0
+   st%_%U0%V0 %S1,%0
    st%_%U0%V0 %S1,%0"
-  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store")
-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false")
-   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no")
-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+  [(set_attr "type" "move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
+   (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false,false")
+   (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no")
+   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")])
 
 (define_expand "movsi"
   [(set (match_operand:SI 0 "move_dest_operand" "")
 ; the iscompact attribute allows the epilogue expander to know for which
 ; insns it should lengthen the return insn.
 ; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
-(define_insn "*movsi_insn"
-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,w,w,w,w,???w,?w,w,Rcq#q,w,Rcq,S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
-       (match_operand:SI 1 "move_src_operand"  "cL,cP,Rcq#q,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
+(define_insn "*movsi_insn"                      ;   0     1     2    3  4 5   6   7   8   9   10  11  12    13   14  15  16     17     18 19   20    21    22 23 24    25 26  27   28   29
+  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,   w,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,VUsc,VUsc")
+       (match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal,  T,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac, Cm3, C32"))]
   "register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode)
    || (CONSTANT_P (operands[1])
    mov%? %0,%1%&       ;0
    mov%? %0,%1%&       ;1
    mov%? %0,%1%&       ;2
-   mov%? %0,%1         ;3
+   mov%? %0,%1%&       ;3
    mov%? %0,%1         ;4
-   ror %0,((%1*2+1) & 0x3f) ;5
-   movl.cl %0,%1       ;6
-   movh.cl %0,%L1>>16  ;7
+   mov%? %0,%1         ;5
+   ror %0,((%1*2+1) & 0x3f) ;6
+   movl.cl %0,%1       ;7
+   movh.cl %0,%L1>>16   ;8
    * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
-   mov%? %0,%1         ;9
-   add %0,%S1          ;10
+   mov%? %0,%1         ;10
+   add %0,%S1          ;11
    * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
-   mov%? %0,%S1%&      ;12
-   mov%? %0,%S1                ;13
-   ld%? %0,%1%&                ;14
-   st%? %1,%0%&                ;15
+   mov%? %0,%S1%&      ;13
+   mov%? %0,%S1                ;14
+   ld%? %0,%1%&                ;15
+   st%? %1,%0%&                ;16
    * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
    * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
-   ld%? %0,%1%&                ;18
-   xld%U1 %0,%1                ;19
-   ld%U1%V1 %0,%1      ;20
-   xst%U0 %1,%0                ;21
-   st%U0%V0 %1,%0       ;22
-   st%U0%V0 %1,%0       ;23
-   st%U0%V0 %S1,%0      ;24"
-  [(set_attr "type" "move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
+   ld%? %0,%1%&                ;19
+   xld%U1 %0,%1                ;20
+   ld%? %0,%1%&                ;21
+   ld%? %0,%1%&                ;22
+   ld%U1%V1 %0,%1      ;23
+   xst%U0 %1,%0                ;24
+   st%? %1,%0%&                ;25
+   st%U0%V0 %1,%0      ;26
+   st%U0%V0 %1,%0      ;27
+   st%U0%V0 %1,%0      ;28
+   st%U0%V0 %S1,%0     ;29"
+  [(set_attr "type" "move,move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,load,load,store,store,store,store,store,store")
+   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false")
    ; Use default length for iscompact to allow for COND_EXEC.  But set length
    ; of Crr to 4.
-   (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
-   (set_attr "predicable" "yes,no,yes,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+   (set_attr "length" "*,*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
+   (set_attr "predicable" "yes,no,yes,no,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
+   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
 
 ;; Sometimes generated by the epilogue code.  We don't want to
 ;; recognize these addresses in general, because the limm is costly,
   "if (prepare_move_operands (operands, SFmode)) DONE;")
 
 (define_insn "*movsf_insn"
-  [(set (match_operand:SF 0 "move_dest_operand" "=w,w,r,m")
-       (match_operand:SF 1 "move_src_operand" "c,E,m,c"))]
+  [(set (match_operand:SF 0 "move_dest_operand"    "=h,w,w,r,m")
+       (match_operand:SF 1 "move_src_operand"   "hCm1,c,E,m,c"))]
   "register_operand (operands[0], SFmode)
    || register_operand (operands[1], SFmode)"
   "@
+   mov%? %0,%1
    mov%? %0,%1
    mov%? %0,%1 ; %A1
    ld%U1%V1 %0,%1
    st%U0%V0 %1,%0"
-  [(set_attr "type" "move,move,load,store")
-   (set_attr "predicable" "yes,yes,no,no")])
+  [(set_attr "type" "move,move,move,load,store")
+   (set_attr "predicable" "no,yes,yes,no,no")
+   (set_attr "iscompact" "true,false,false,false,false")])
 
 (define_expand "movdf"
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
 )
 
 (define_insn "*extendhisi2_i"
-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
-       (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
+  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,Rcq,r,r")
+       (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Ucd,Uex,m")))]
   ""
   "@
    sex%_%? %0,%1%&
    sex%_ %0,%1
+   ldh%?.x %0,%1%&
    ld%_.x%U1%V1 %0,%1
    ld%_.x%U1%V1 %0,%1"
-  [(set_attr "type" "unary,unary,load,load")
-   (set_attr "iscompact" "true,false,false,false")
-   (set_attr "length" "*,*,4,8")])
+  [(set_attr "type" "unary,unary,load,load,load")
+   (set_attr "iscompact" "true,false,true,false,false")
+   (set_attr "length" "*,*,*,4,8")])
 
 (define_expand "extendhisi2"
   [(set (match_operand:SI 0 "dest_reg_operand" "")
      operands[1] = arc_rewrite_small_data (operands[1]);")
 
 (define_insn "andsi3_i"
-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw,w,w,w,w,Rrq,w,Rcw,w,W")
-       (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,0,0,Rcqq,0,c,0,0,0,0,c,c,c,c,Rrq,0,0,c,o")
-               (match_operand:SI 2 "nonmemory_operand" "Rcqq,0,C1p,Ccp,Cux,cL,0,C1p,Ccp,CnL,I,Lc,C1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
+  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,   Rcw,Rcw,Rcw,Rcw, w,     w,  w,  w,Rrq,w,Rcw,  w,W")
+       (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,   0,   0,Rcqq,  0,  c,     0,  0,  0,  0, c,     c,  c,  c,Rrq,0,  0,  c,o")
+               (match_operand:SI 2 "nonmemory_operand"  "Rcqq,  0, C1p, Ccp, Cux, cL,  0,C2pC1p,Ccp,CnL,  I,Lc,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
   "(register_operand (operands[1], SImode)
     && nonmemory_operand (operands[2], SImode))
    || (memory_operand (operands[1], SImode)
       return "and%? %0,%1,%2%&";
     case 1: case 6:
       return "and%? %0,%2,%1%&";
-    case 2: case 7: case 12:
+    case 2:
       return "bmsk%? %0,%1,%Z2%&";
+    case 7: case 12:
+     if (satisfies_constraint_C2p (operands[2]))
+       {
+       operands[2] = GEN_INT ((~INTVAL (operands[2])));
+       return "bmskn%? %0,%1,%Z2%&";
+       }
+     else
+       {
+       return "bmsk%? %0,%1,%Z2%&";
+       }
     case 3: case 8: case 13:
       return "bclr%? %0,%1,%M2%&";
     case 4:
 ;; modifed cc user if second, but not first operand is a compact register.
 (define_insn "cmpsi_cc_insn_mixed"
   [(set (reg:CC CC_REG)
-       (compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,c,c, qRcq, c")
-                   (match_operand:SI 1 "nonmemory_operand" "cO,cI,cL,  Cal, Cal")))]
+       (compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,  h, c, c,qRcq,c")
+                   (match_operand:SI 1 "nonmemory_operand"   "cO,Cm1,cI,cL, Cal,Cal")))]
   ""
   "cmp%? %0,%B1%&"
   [(set_attr "type" "compare")
-   (set_attr "iscompact" "true,false,false,true_limm,false")
-   (set_attr "predicable" "no,no,yes,no,yes")
+   (set_attr "iscompact" "true,true,false,false,true_limm,false")
+   (set_attr "predicable" "no,no,no,yes,no,yes")
    (set_attr "cond" "set")
-   (set_attr "length" "*,4,4,*,8")])
+   (set_attr "length" "*,*,4,4,*,8")])
 
 (define_insn "*cmpsi_cc_zn_insn"
   [(set (reg:CC_ZN CC_REG)
 
 (define_insn "*cmpsi_cc_c_insn"
   [(set (reg:CC_C CC_REG)
-       (compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq, c,Rcqq,  c")
-                     (match_operand:SI 1 "nonmemory_operand" "cO,  cI, Cal,Cal")))]
+       (compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq,  h, c,Rcqq,  c")
+                     (match_operand:SI 1 "nonmemory_operand"   "cO,Cm1,cI, Cal,Cal")))]
   ""
   "cmp%? %0,%S1%&"
   [(set_attr "type" "compare")
-   (set_attr "iscompact" "true,false,true_limm,false")
+   (set_attr "iscompact" "true,true,false,true_limm,false")
    (set_attr "cond" "set")
-   (set_attr "length" "*,4,*,8")])
+   (set_attr "length" "*,*,4,*,8")])
 
 ;; Next come the scc insns.
 
 ; cond_exec patterns
 (define_insn "*movsi_ne"
   [(cond_exec
-     (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc,Rcc,Rcc") (const_int 0))
-     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
-         (match_operand:SI 1 "nonmemory_operand" "C_0,Lc,?Cal")))]
+     (ne (match_operand:CC_Z 2 "cc_use_register"    "Rcc,  Rcc,  Rcc,Rcc,Rcc") (const_int 0))
+     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q,  w,w")
+         (match_operand:SI 1 "nonmemory_operand"   "C_0,    h, ?Cal, Lc,?Cal")))]
   ""
   "@
        * current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
+       * current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
+       * current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
        mov.ne %0,%1
        mov.ne %0,%S1"
-  [(set_attr "type" "cmove,cmove,cmove")
-   (set_attr "iscompact" "true,false,false")
-   (set_attr "length" "2,4,8")])
+  [(set_attr "type" "cmove")
+   (set_attr "iscompact" "true,true,true_limm,false,false")
+   (set_attr "length" "2,2,6,4,8")
+   (set_attr "cpu_facility" "*,av2,av2,*,*")])
 
 (define_insn "*movsi_cond_exec"
   [(cond_exec
index 5069d7d9746de3dbd7621a755a7435fdf70b168f..b7bf2d39c4e880e2e558b36d485f0958538fe1ff 100644 (file)
   (and (match_code "const_int")
        (match_test "ival && IS_POWEROF2_P (ival + 1)")))
 
+(define_constraint "C2p"
+ "@internal
+  constant such that (~x)+1 is a power of two, and x < -1"
+  (and (match_code "const_int")
+       (match_test "TARGET_V2
+                   && (ival < -1)
+                   && IS_POWEROF2_P ((~ival) + 1)")))
+
 (define_constraint "C3p"
  "@internal
   constant int used to select xbfu a,b,u6 instruction.  The values accepted are 1 and 2."
   "@internal
    A valid memory operand for ARCompact load instructions"
   (and (match_code "mem")
-       (match_test "compact_load_memory_operand (op, VOIDmode)")))
+       (match_test "compact_memory_operand_p (op, mode, false, false)")))
+
+(define_memory_constraint "Uts"
+  "@internal
+   A valid memory operand for ARCompact load instructions scaled"
+  (and (match_code "mem")
+       (match_test "compact_memory_operand_p (op, mode, false, TARGET_CODE_DENSITY)")))
 
 (define_memory_constraint "S"
   "@internal
    "@internal
     A valid _small-data_ memory operand for ARCompact instructions"
    (and (match_code "mem")
-        (match_test "compact_sda_memory_operand (op, VOIDmode)")))
+       (match_test "compact_sda_memory_operand (op, VOIDmode)")))
 
 (define_memory_constraint "Usc"
   "@internal
   (and (match_code "const_int")
        (match_test "IS_ZERO (ival)")))
 
+(define_constraint "Cm1"
+  "@internal
+   Integer signed constant in the interval [-1,6]"
+  (and (match_code "const_int")
+       (match_test "(ival >= -1) && (ival <=6)")
+       (match_test "TARGET_V2")))
+
 (define_constraint "Cm2"
   "@internal
    A signed 9-bit integer constant."
   (and (match_code "const_int")
        (match_test "(ival >= -256) && (ival <=255)")))
 
+(define_constraint "Cm3"
+  "@internal
+   A signed 6-bit integer constant."
+  (and (match_code "const_int")
+       (match_test "(ival >= -32) && (ival <=31)")
+       (match_test "TARGET_V2")))
+
 (define_constraint "C62"
   "@internal
    An unsigned 6-bit integer constant, up to 62."
    An unsigned 16-bit integer constant"
   (and (match_code "const_int")
        (match_test "UNSIGNED_INT16 (ival)")))
+
+; Memory addresses suited for code density load ops
+(define_memory_constraint "Ucd"
+  "@internal
+   A valid memory operand for use with code density load ops"
+  (and (match_code "mem")
+       (match_test "compact_memory_operand_p (op, mode, true, false)")
+       (match_test "TARGET_V2")))
+
+(define_register_constraint "h"
+  "TARGET_V2 ? AC16_H_REGS : NO_REGS"
+  "5-bit h register set except @code{r30} and @code{r29}:
+   @code{r0}-@code{r31}, nonfixed core register")
+
+; Code density registers
+(define_register_constraint "Rcd"
+  "TARGET_CODE_DENSITY ? R0R3_CD_REGS : NO_REGS"
+  "@internal
+   core register @code{r0}-@code{r3}")
+
+(define_register_constraint "Rsd"
+  "TARGET_CODE_DENSITY ? R0R1_CD_REGS : NO_REGS"
+  "@internal
+   core register @code{r0}-@code{r1}")
+
+(define_register_constraint "Rzd"
+  "TARGET_CODE_DENSITY ? R0_REGS : NO_REGS"
+  "@internal
+   @code{r0} register for code density instructions.")
index 8e4b4b40c543c46b471715664322f7acdf2c4858..f85f931d46011af6ed0533e38be455af5cede4e1 100644 (file)
   }
 )
 
-;; Return true if OP is an acceptable memory operand for ARCompact
-;; 16-bit load instructions.
-(define_predicate "compact_load_memory_operand"
-  (match_code "mem")
-{
-  rtx addr, plus0, plus1;
-  int size, off;
-
-  /* Eliminate non-memory operations.  */
-  if (GET_CODE (op) != MEM)
-    return 0;
-
-  /* .di instructions have no 16-bit form.  */
-  if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
-     return 0;
-
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  size = GET_MODE_SIZE (mode);
-
-  /* dword operations really put out 2 instructions, so eliminate them.  */
-  if (size > UNITS_PER_WORD)
-    return 0;
-
-  /* Decode the address now.  */
-  addr = XEXP (op, 0);
-  switch (GET_CODE (addr))
-    {
-    case REG:
-      return (REGNO (addr) >= FIRST_PSEUDO_REGISTER
-             || COMPACT_GP_REG_P (REGNO (addr))
-             || (SP_REG_P (REGNO (addr)) && (size != 2)));
-       /* Reverting for the moment since ldw_s does not have sp as a valid
-          parameter.  */
-    case PLUS:
-      plus0 = XEXP (addr, 0);
-      plus1 = XEXP (addr, 1);
-
-      if ((GET_CODE (plus0) == REG)
-         && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
-             || COMPACT_GP_REG_P (REGNO (plus0)))
-         && ((GET_CODE (plus1) == REG)
-             && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
-                 || COMPACT_GP_REG_P (REGNO (plus1)))))
-       {
-         return 1;
-       }
-
-      if ((GET_CODE (plus0) == REG)
-         && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
-             || COMPACT_GP_REG_P (REGNO (plus0)))
-         && (GET_CODE (plus1) == CONST_INT))
-       {
-         off = INTVAL (plus1);
-
-         /* Negative offset is not supported in 16-bit load/store insns.  */
-         if (off < 0)
-           return 0;
-
-         switch (size)
-           {
-           case 1:
-             return (off < 32);
-           case 2:
-             return ((off < 64) && (off % 2 == 0));
-           case 4:
-             return ((off < 128) && (off % 4 == 0));
-           }
-       }
-
-      if ((GET_CODE (plus0) == REG)
-         && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
-             || SP_REG_P (REGNO (plus0)))
-         && (GET_CODE (plus1) == CONST_INT))
-       {
-         off = INTVAL (plus1);
-         return ((size != 2) && (off >= 0 && off < 128) && (off % 4 == 0));
-       }
-    default:
-      break ;
-      /* TODO: 'gp' and 'pcl' are to supported as base address operand
-              for 16-bit load instructions.  */
-    }
-  return 0;
-
-}
-)
-
 ;; Return true if OP is an acceptable memory operand for ARCompact
 ;; 16-bit store instructions
 (define_predicate "compact_store_memory_operand"