diff mbox

[ARC] Add new ARCv2 instructions.

Message ID 1461939628-30722-1-git-send-email-claziss@synopsys.com
State New
Headers show

Commit Message

Claudiu Zissulescu April 29, 2016, 2:20 p.m. UTC
Please find the updated patch.

Ok to commit?
Claudiu

gcc/
2016-04-20  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.
---
 gcc/config/arc/arc-protos.h   |   2 +-
 gcc/config/arc/arc.c          | 146 +++++++++++++++++++++++++++++++++++++++
 gcc/config/arc/arc.h          |   9 +++
 gcc/config/arc/arc.md         | 154 ++++++++++++++++++++++++------------------
 gcc/config/arc/constraints.md |  61 ++++++++++++++++-
 gcc/config/arc/predicates.md  |  89 ------------------------
 6 files changed, 304 insertions(+), 157 deletions(-)

Comments

Joern Wolfgang Rennecke April 29, 2016, 4:18 p.m. UTC | #1
On 29/04/16 15:20, Claudiu Zissulescu wrote:
> Please find the updated patch.
>
> Ok to commit?
OK.
diff mbox

Patch

diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 3bf28a0..8630e2d 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -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
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index dfaea7b..a54fddb 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -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"
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index bc14d11..f6b85ea 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -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 */		\
 }
 
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index d1a9159..944c7fe 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -620,14 +620,15 @@ 
 ; 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
@@ -640,10 +641,10 @@ 
    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" "")
@@ -652,8 +653,8 @@ 
   "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])
@@ -665,6 +666,7 @@ 
    mov%? %0,%1%&
    mov%? %0,%1%&
    mov%? %0,%1%&
+   mov%? %0,%1%&
    mov%? %0,%1
    mov%? %0,%1
    mov%? %0,%1
@@ -677,11 +679,12 @@ 
    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" "")
@@ -699,9 +702,9 @@ 
 ; 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])
@@ -713,35 +716,40 @@ 
    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,
@@ -1136,17 +1144,19 @@ 
   "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" "")
@@ -1664,17 +1674,18 @@ 
 )
 
 (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" "")
@@ -3041,9 +3052,9 @@ 
      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)
@@ -3055,8 +3066,18 @@ 
       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:
@@ -3368,15 +3389,15 @@ 
 ;; 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)
@@ -3452,14 +3473,14 @@ 
 
 (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.
 
@@ -3552,17 +3573,20 @@ 
 ; 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
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index 5069d7d..b7bf2d3 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -226,6 +226,14 @@ 
   (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."
@@ -317,7 +325,13 @@ 
   "@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
@@ -340,7 +354,7 @@ 
    "@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
@@ -483,12 +497,26 @@ 
   (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."
@@ -511,3 +539,32 @@ 
    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.")
diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
index 8e4b4b4..f85f931 100644
--- a/gcc/config/arc/predicates.md
+++ b/gcc/config/arc/predicates.md
@@ -185,95 +185,6 @@ 
 )
 
 ;; 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"
   (match_code "mem")