public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] Revert "arc: Add new opcode functions for ARCv3 ISA."
@ 2023-09-25 14:08 Claudiu Zissulescu
  0 siblings, 0 replies; only message in thread
From: Claudiu Zissulescu @ 2023-09-25 14:08 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3b7e24aa56fbd036121e62935b22ff5cb8f253da

commit 3b7e24aa56fbd036121e62935b22ff5cb8f253da
Author: Claudiu Zissulescu <claziss@gmail.com>
Date:   Mon Sep 25 17:02:19 2023 +0300

    Revert "arc: Add new opcode functions for ARCv3 ISA."
    
    This reverts commit c99dc76089a2de97ea0ee755aa8e87037a17b6d6.

Diff:
---
 opcodes/Makefile.am          |    1 -
 opcodes/Makefile.in          |    2 -
 opcodes/arc-dis.c            |  290 ++--
 opcodes/arc-ext-tbl.h        |  124 ++
 opcodes/arc-flag-classes.def |  125 --
 opcodes/arc-flag.def         |  179 ---
 opcodes/arc-fxi.h            |   60 -
 opcodes/arc-opc.c            | 2990 ++++++++++++++++++++++++++++++++++++++++--
 opcodes/arc-operands.def     |  502 -------
 opcodes/arc-regs.h           |    8 +-
 opcodes/arc64-opc.c          |  834 ------------
 opcodes/arcxx-opc.inc        | 1840 --------------------------
 opcodes/configure            |    1 -
 opcodes/configure.ac         |    1 -
 opcodes/disassemble.c        |    6 -
 15 files changed, 3091 insertions(+), 3872 deletions(-)

diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index effcd41b6ae..5804dd1ab38 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -116,7 +116,6 @@ TARGET32_LIBOPCODES_CFILES = \
 	arc-dis.c \
 	arc-ext.c \
 	arc-opc.c \
-	arc64-opc.c \
 	arm-dis.c \
 	avr-dis.c \
 	bfin-dis.c \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index f207cf57f44..29c26263061 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -508,7 +508,6 @@ TARGET32_LIBOPCODES_CFILES = \
 	arc-dis.c \
 	arc-ext.c \
 	arc-opc.c \
-	arc64-opc.c \
 	arm-dis.c \
 	avr-dis.c \
 	bfin-dis.c \
@@ -877,7 +876,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-ext.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-opc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc64-opc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avr-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bfin-dis.Plo@am__quote@
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index dbcd0dbd7f8..59b668ff64e 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -60,7 +60,7 @@ struct arc_disassemble_info
   /* Instruction length w/o limm field.  */
   unsigned insn_len;
 
-  /* true if we have limm.  */
+  /* TRUE if we have limm.  */
   bool limm_p;
 
   /* LIMM value, if exists.  */
@@ -85,7 +85,7 @@ static const char * const regnames[64] =
   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
-  "r24", "r25", "r26", "fp", "sp", "ilink", "r30", "blink",
+  "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
 
   "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
   "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
@@ -93,29 +93,6 @@ static const char * const regnames[64] =
   "r56", "r57", "r58", "r59", "lp_count", "reserved", "LIMM", "pcl"
 };
 
-typedef struct regmod
-{
-  const unsigned int index;
-  const unsigned int isa;
-  const char *rname;
-} regmod_t;
-
-static regmod_t regmods[] =
-{
-  { 26, ARC_OPCODE_ARCV1 | ARC_OPCODE_ARCV2, "gp" },
-  { 29, ARC_OPCODE_ARCV1, "ilink1" },
-  { 30, ARC_OPCODE_ARCV1, "ilink2" },
-  { 0, ARC_OPCODE_NONE, 0 }
-};
-
-static const char * const fpnames[32] =
-{
-  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
-  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
-  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
-  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
-};
-
 static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
 {
   "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
@@ -149,6 +126,7 @@ static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
 static bool print_hex = false;
 
 /* Macros section.  */
+
 #ifdef DEBUG
 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
 #else
@@ -162,29 +140,8 @@ static bool print_hex = false;
 #define BITS(word,s,e)  (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
 #define OPCODE_32BIT_INSN(word)	(BITS ((word), 27, 31))
 
-#define REG_PCL    63
-#define REG_LIMM   62
-#define REG_LIMM_S 30
-#define REG_U32    62
-#define REG_S32    60
-
 /* Functions implementation.  */
 
-static const char *
-getregname (unsigned int index, unsigned int isa_mask)
-{
-  regmod_t *iregmods = regmods;
-  while (iregmods->rname)
-    {
-      if (index == iregmods->index
-	  && (isa_mask & iregmods->isa))
-	return iregmods->rname;
-      iregmods ++;
-    }
-
-  return regnames[index % 64];
-}
-
 /* Initialize private data.  */
 static bool
 init_arc_disasm_info (struct disassemble_info *info)
@@ -213,7 +170,7 @@ add_to_decodelist (insn_class_t     insn_class,
   decodelist = t;
 }
 
-/* Return true if we need to skip the opcode from being
+/* Return TRUE if we need to skip the opcode from being
    disassembled.  */
 
 static bool
@@ -320,7 +277,7 @@ find_format_from_table (struct disassemble_info *info,
       if (arc_opcode_len (opcode) != (int) insn_len)
 	continue;
 
-      if ((insn & opcode->mask) != (opcode->mask & opcode->opcode))
+      if ((insn & opcode->mask) != opcode->opcode)
 	continue;
 
       *has_limm = false;
@@ -328,7 +285,7 @@ find_format_from_table (struct disassemble_info *info,
       /* Possible candidate, check the operands.  */
       for (opidx = opcode->operands; *opidx; opidx++)
 	{
-	  int value, slimmind;
+	  int value, limmind;
 	  const struct arc_operand *operand = &arc_operands[*opidx];
 
 	  if (operand->flags & ARC_OPERAND_FAKE)
@@ -339,19 +296,19 @@ find_format_from_table (struct disassemble_info *info,
 	  else
 	    value = (insn >> operand->shift) & ((1ull << operand->bits) - 1);
 
-	  /* Check for (short) LIMM indicator.  If it is there, then
-	     make sure we pick the right format.  */
-	  slimmind = (isa_mask & ARC_OPCODE_ARCVx) ?  REG_LIMM_S : REG_LIMM;
+	  /* Check for LIMM indicator.  If it is there, then make sure
+	     we pick the right format.  */
+	  limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
 	  if (operand->flags & ARC_OPERAND_IR
 	      && !(operand->flags & ARC_OPERAND_LIMM))
-	    if ((value == REG_LIMM && insn_len == 4)
-		|| (value == slimmind && insn_len == 2)
-		|| (isa_mask & ARC_OPCODE_ARC64
-		    && (value == REG_S32) && (insn_len == 4)))
-	      {
-		invalid = true;
-		break;
-	      }
+	    {
+	      if ((value == 0x3E && insn_len == 4)
+		  || (value == limmind && insn_len == 2))
+		{
+		  invalid = true;
+		  break;
+		}
+	    }
 
 	  if (operand->flags & ARC_OPERAND_LIMM
 	      && !(operand->flags & ARC_OPERAND_DUPLICATE))
@@ -381,15 +338,11 @@ find_format_from_table (struct disassemble_info *info,
 
 	  for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
 	    {
-	      bool tmp = false;
 	      const struct arc_flag_operand *flg_operand =
 		&arc_flag_operands[*flgopridx];
 
-	      if (cl_flags->extract)
-		value = (*cl_flags->extract)(insn, &tmp);
-	      else
-		value = (insn >> flg_operand->shift)
-		  & ((1 << flg_operand->bits) - 1);
+	      value = (insn >> flg_operand->shift)
+		& ((1 << flg_operand->bits) - 1);
 	      if (value == flg_operand->code)
 		foundA = 1;
 	      if (value)
@@ -443,15 +396,15 @@ find_format_from_table (struct disassemble_info *info,
    the found opcode requires a LIMM then the LIMM value will be loaded into a
    field of ITER.
 
-   This function returns true in almost all cases, false is reserved to
+   This function returns TRUE in almost all cases, FALSE is reserved to
    indicate an error (failing to find an opcode is not an error) a returned
-   result of false would indicate that the disassembler can't continue.
+   result of FALSE would indicate that the disassembler can't continue.
 
-   If no matching opcode is found then the returned result will be true, the
+   If no matching opcode is found then the returned result will be TRUE, the
    value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
    INSN_LEN will be unchanged.
 
-   If a matching opcode is found, then the returned result will be true, the
+   If a matching opcode is found, then the returned result will be TRUE, the
    opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
    4 if the instruction requires a LIMM, and the LIMM value will have been
    loaded into a field of ITER.  Finally, ITER will have been initialised so
@@ -468,14 +421,11 @@ find_format (bfd_vma                       memaddr,
              struct arc_operand_iterator * iter)
 {
   const struct arc_opcode *opcode = NULL;
-  const struct arc_opcode *opcodeList = NULL;
   bool needs_limm = false;
   const extInstruction_t *einsn, *i;
   unsigned limm = 0;
   struct arc_disassemble_info *arc_infop = info->private_data;
 
-  opcodeList = arc_opcodes;
-
   /* First, try the extension instructions.  */
   if (*insn_len == 4)
     {
@@ -502,7 +452,7 @@ find_format (bfd_vma                       memaddr,
 
   /* Then, try finding the first match in the opcode table.  */
   if (opcode == NULL)
-    opcode = find_format_from_table (info, opcodeList, insn, *insn_len,
+    opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
 				     isa_mask, &needs_limm, true);
 
   if (opcode != NULL && needs_limm)
@@ -592,14 +542,8 @@ print_flags (const struct arc_opcode *opcode,
 	  if (!flg_operand->favail)
 	    continue;
 
-	  if (cl_flags->extract)
-	    {
-	      bool tmp = false;
-	      value = (*cl_flags->extract)(insn[0], &tmp);
-	    }
-	  else
-	    value = (insn[0] >> flg_operand->shift)
-	      & ((1 << flg_operand->bits) - 1);
+	  value = (insn[0] >> flg_operand->shift)
+	    & ((1 << flg_operand->bits) - 1);
 	  if (value == flg_operand->code)
 	    {
 	       /* FIXME!: print correctly nt/t flag.  */
@@ -702,59 +646,34 @@ arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
 {
   bfd_byte major_opcode = msb >> 3;
 
-  switch (info->arch)
+  switch (info->mach)
     {
-    case bfd_arch_arc:
-      switch (info->mach)
-	{
-	case bfd_mach_arc_arc700:
-	  /* The nps400 extension set requires this special casing of
-	     the instruction length calculation.  Right now this is
-	     not causing any problems as none of the known extensions
-	     overlap in opcode space, but, if they ever do then we
-	     might need to start carrying information around in the
-	     elf about which extensions are in use.  */
-	  if (major_opcode == 0xb)
-	    {
-	      bfd_byte minor_opcode = lsb & 0x1f;
-
-	      if (minor_opcode < 4)
-		return 6;
-	      else if (minor_opcode == 0x10 || minor_opcode == 0x11)
-		return 8;
-	    }
-	  if (major_opcode == 0xa)
-	    {
-	      return 8;
-	    }
-	  /* Fall through.  */
-	case bfd_mach_arc_arc600:
-	  return (major_opcode > 0xb) ? 2 : 4;
-	  break;
-
-	case bfd_mach_arc_arcv2:
-	  return (major_opcode > 0x7) ? 2 : 4;
-	  break;
+    case bfd_mach_arc_arc700:
+      /* The nps400 extension set requires this special casing of the
+	 instruction length calculation.  Right now this is not causing any
+	 problems as none of the known extensions overlap in opcode space,
+	 but, if they ever do then we might need to start carrying
+	 information around in the elf about which extensions are in use.  */
+      if (major_opcode == 0xb)
+        {
+          bfd_byte minor_opcode = lsb & 0x1f;
 
-	default:
-	  return 0;
-	}
+	  if (minor_opcode < 4)
+	    return 6;
+	  else if (minor_opcode == 0x10 || minor_opcode == 0x11)
+	    return 8;
+        }
+      if (major_opcode == 0xa)
+        {
+          return 8;
+        }
+      /* Fall through.  */
+    case bfd_mach_arc_arc600:
+      return (major_opcode > 0xb) ? 2 : 4;
       break;
 
-    case bfd_arch_arc64:
-      switch (info->mach)
-	{
-	case bfd_mach_arcv3_32:
-	case bfd_mach_arcv3_64:
-	  if (major_opcode == 0x0b
-	      || major_opcode == 0x0d
-	      || major_opcode == 0x1c)
-	    return 4;
-	  return (major_opcode > 0x7) ? 2 : 4;
-
-	default:
-	  return 0;
-	}
+    case bfd_mach_arc_arcv2:
+      return (major_opcode > 0x7) ? 2 : 4;
       break;
 
     default:
@@ -804,8 +723,8 @@ extract_operand_value (const struct arc_operand *operand,
   return value;
 }
 
-/* Find the next operand, and the operands value from ITER.  Return true if
-   there is another operand, otherwise return false.  If there is an
+/* Find the next operand, and the operands value from ITER.  Return TRUE if
+   there is another operand, otherwise return FALSE.  If there is an
    operand returned then the operand is placed into OPERAND, and the value
    into VALUE.  If there is no operand returned then OPERAND and VALUE are
    unchanged.  */
@@ -889,18 +808,14 @@ parse_option (const char *option)
 }
 
 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA)			\
-  { #NAME, ARC_OPCODE_ARC600, "ARC600" },
+  { #NAME, ARC_OPCODE_ARC600, "ARC600" }
 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA)			\
-  { #NAME, ARC_OPCODE_ARC700, "ARC700" },
+  { #NAME, ARC_OPCODE_ARC700, "ARC700" }
 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA)			\
-  { #NAME,  ARC_OPCODE_ARCv2EM, "ARC EM" },
+  { #NAME,  ARC_OPCODE_ARCv2EM, "ARC EM" }
 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA)			\
-  { #NAME,  ARC_OPCODE_ARCv2HS, "ARC HS" },
-#define ARC_CPU_TYPE_A64x(NAME,EXTRA)			\
-  { #NAME,  ARC_OPCODE_ARC64, "ARC64" },
-#define ARC_CPU_TYPE_A32x(NAME,EXTRA)			\
-  { #NAME,  ARC_OPCODE_ARC64, "ARC32" },
-#define ARC_CPU_TYPE_NONE			\
+  { #NAME,  ARC_OPCODE_ARCv2HS, "ARC HS" }
+#define ARC_CPU_TYPE_NONE				\
   { 0, 0, 0 }
 
 /* A table of CPU names and opcode sets.  */
@@ -1035,8 +950,7 @@ print_insn_arc (bfd_vma memaddr,
   bool open_braket;
   int size;
   const struct arc_operand *operand;
-  int value;
-  bfd_vma vpcl;
+  int value, vpcl;
   struct arc_operand_iterator iter;
   struct arc_disassemble_info *arc_infop;
   bool rpcl = false, rset = false;
@@ -1064,54 +978,25 @@ print_insn_arc (bfd_vma memaddr,
       if (info->section && info->section->owner)
 	header = elf_elfheader (info->section->owner);
 
-      switch (info->arch)
+      switch (info->mach)
 	{
-	case bfd_arch_arc:
-	  switch (info->mach)
-	    {
-	    case bfd_mach_arc_arc700:
-	      isa_mask = ARC_OPCODE_ARC700;
-	      break;
-
-	    case bfd_mach_arc_arc600:
-	      isa_mask = ARC_OPCODE_ARC600;
-	      break;
-
-	    case bfd_mach_arc_arcv2:
-	    default:
-	      isa_mask = ARC_OPCODE_ARCv2EM;
-	      /* TODO: Perhaps remove definition of header since it is
-		 only used at this location.  */
-	      if (header != NULL
-		  && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
-		isa_mask = ARC_OPCODE_ARCv2HS;
-	      break;
-	    }
+	case bfd_mach_arc_arc700:
+	  isa_mask = ARC_OPCODE_ARC700;
 	  break;
 
-	case bfd_arch_arc64:
-	  switch (info->mach)
-	    {
-	    case bfd_mach_arcv3_64:
-	      isa_mask = ARC_OPCODE_ARC64;
-	      break;
-
-	    case bfd_mach_arcv3_32:
-	      isa_mask = ARC_OPCODE_ARC32;
-	      break;
-
-	    default:
-	      /* xgettext:c-format */
-	      opcodes_error_handler (_("unrecognised arc64 disassembler \
-variant"));
-	      return -1;
-	    }
+	case bfd_mach_arc_arc600:
+	  isa_mask = ARC_OPCODE_ARC600;
 	  break;
 
+	case bfd_mach_arc_arcv2:
 	default:
-	  /* xgettext:c-format */
-	  opcodes_error_handler (_("unrecognised disassembler architecture"));
-	  return -1;
+	  isa_mask = ARC_OPCODE_ARCv2EM;
+	  /* TODO: Perhaps remove definition of header since it is only used at
+	     this location.  */
+	  if (header != NULL
+	      && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
+	    isa_mask = ARC_OPCODE_ARCv2HS;
+	  break;
 	}
     }
   else
@@ -1404,10 +1289,8 @@ variant"));
 	  rpcl = true;
 	  vpcl = value;
 	  rset = true;
-	  if ((operand->flags & ARC_OPERAND_LIMM)
-	      && (operand->flags & ARC_OPERAND_ALIGNED32))
-	    vpcl <<= 2;
-	  info->target = (bfd_vma) (memaddr & ~3) + vpcl;
+
+	  info->target = (bfd_vma) (memaddr & ~3) + value;
 	}
       else if (!(operand->flags & ARC_OPERAND_IR))
 	{
@@ -1420,15 +1303,10 @@ variant"));
 	{
 	  const char *rname;
 
-	  assert (value >= 0 && value < 64);
+	  assert (value >=0 && value < 64);
 	  rname = arcExtMap_coreRegName (value);
 	  if (!rname)
-	    {
-	      if (operand->flags & ARC_OPERAND_FP)
-		rname = fpnames[value & 0x1f];
-	      else
-		rname = getregname (value, isa_mask);
-	    }
+	    rname = regnames[value];
 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
 					"%s", rname);
 
@@ -1438,10 +1316,8 @@ variant"));
 	      if ((value & 0x01) == 0)
 		{
 		  rname = arcExtMap_coreRegName (value + 1);
-		  if (operand->flags & ARC_OPERAND_FP)
-		    rname = fpnames[(value + 1) & 0x1f];
-		  else
-		    rname = getregname (value + 1, isa_mask);
+		  if (!rname)
+		    rname = regnames[value + 1];
 		}
 	      else
 		rname = _("\nWarning: illegal use of double register "
@@ -1449,7 +1325,7 @@ variant"));
 	      (*info->fprintf_styled_func) (info->stream, dis_style_register,
 					    "%s", rname);
 	    }
-	  if (value == REG_PCL)
+	  if (value == 63)
 	    rpcl = true;
 	  else
 	    rpcl = false;
@@ -1463,12 +1339,8 @@ variant"));
 					  "%s", rname);
 	  else
 	    {
-	      if (operand->flags & ARC_OPERAND_SIGNED)
-		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
-					      "%d@s32", value);
-	      else
-		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
-					      "%#x", value);
+	      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+					    "%#x", value);
 	      if (info->insn_type == dis_branch
 		  || info->insn_type == dis_jsr)
 		info->target = (bfd_vma) value;
@@ -1546,7 +1418,7 @@ variant"));
 	    = ARC_OPERAND_KIND_LIMM;
 	  /* It is not important to have exactly the LIMM indicator
 	     here.  */
-	  arc_infop->operands[arc_infop->operands_count].value = REG_PCL;
+	  arc_infop->operands[arc_infop->operands_count].value = 63;
 	}
       else
 	{
diff --git a/opcodes/arc-ext-tbl.h b/opcodes/arc-ext-tbl.h
new file mode 100644
index 00000000000..d230b610e8c
--- /dev/null
+++ b/opcodes/arc-ext-tbl.h
@@ -0,0 +1,124 @@
+/* ARC instruction defintions.
+   Copyright (C) 2016-2023 Free Software Foundation, Inc.
+
+   Contributed by Claudiu Zissulescu (claziss@synopsys.com)
+
+   This file is part of libopcodes.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Common combinations of FLAGS.  */
+#define FLAGS_NONE { 0 }
+#define FLAGS_F    { C_F }
+#define FLAGS_CC   { C_CC }
+#define FLAGS_CCF  { C_CC, C_F }
+
+/* Common combination of arguments.  */
+#define ARG_NONE		{ 0 }
+#define ARG_32BIT_RARBRC	{ RA, RB, RC }
+#define ARG_32BIT_ZARBRC	{ ZA, RB, RC }
+#define ARG_32BIT_RBRBRC	{ RB, RBdup, RC }
+#define ARG_32BIT_RARBU6	{ RA, RB, UIMM6_20 }
+#define ARG_32BIT_ZARBU6	{ ZA, RB, UIMM6_20 }
+#define ARG_32BIT_RBRBU6	{ RB, RBdup, UIMM6_20 }
+#define ARG_32BIT_RBRBS12	{ RB, RBdup, SIMM12_20 }
+#define ARG_32BIT_RALIMMRC	{ RA, LIMM, RC }
+#define ARG_32BIT_RARBLIMM	{ RA, RB, LIMM }
+#define ARG_32BIT_ZALIMMRC	{ ZA, LIMM, RC }
+#define ARG_32BIT_ZARBLIMM	{ ZA, RB, LIMM }
+
+#define ARG_32BIT_RBRBLIMM	{ RB, RBdup, LIMM }
+#define ARG_32BIT_RALIMMU6	{ RA, LIMM, UIMM6_20 }
+#define ARG_32BIT_ZALIMMU6	{ ZA, LIMM, UIMM6_20 }
+
+#define ARG_32BIT_ZALIMMS12	{ ZA, LIMM, SIMM12_20 }
+#define ARG_32BIT_RALIMMLIMM	{ RA, LIMM, LIMMdup }
+#define ARG_32BIT_ZALIMMLIMM	{ ZA, LIMM, LIMMdup }
+
+#define ARG_32BIT_RBRC   { RB, RC }
+#define ARG_32BIT_ZARC   { ZA, RC }
+#define ARG_32BIT_RBU6   { RB, UIMM6_20 }
+#define ARG_32BIT_ZAU6   { ZA, UIMM6_20 }
+#define ARG_32BIT_RBLIMM { RB, LIMM }
+#define ARG_32BIT_ZALIMM { ZA, LIMM }
+
+/* Macro to generate 2 operand extension instruction.  */
+#define EXTINSN2OPF(NAME, CPU, CLASS, SCLASS, MOP, SOP, FL)	 \
+  { NAME, INSN2OP_BC (MOP,SOP), MINSN2OP_BC, CPU, CLASS, SCLASS, \
+      ARG_32BIT_RBRC,   FL },					 \
+  { NAME, INSN2OP_0C (MOP,SOP), MINSN2OP_0C, CPU, CLASS, SCLASS, \
+      ARG_32BIT_ZARC,   FL },					 \
+  { NAME, INSN2OP_BU (MOP,SOP), MINSN2OP_BU, CPU, CLASS, SCLASS, \
+      ARG_32BIT_RBU6,   FL },					 \
+  { NAME, INSN2OP_0U (MOP,SOP), MINSN2OP_0U, CPU, CLASS, SCLASS, \
+      ARG_32BIT_ZAU6,   FL },					 \
+  { NAME, INSN2OP_BL (MOP,SOP), MINSN2OP_BL, CPU, CLASS, SCLASS, \
+      ARG_32BIT_RBLIMM, FL },					 \
+  { NAME, INSN2OP_0L (MOP,SOP), MINSN2OP_0L, CPU, CLASS, SCLASS, \
+      ARG_32BIT_ZALIMM, FL },
+
+#define EXTINSN2OP(NAME, CPU, CLASS, SCLASS, MOP, SOP)		 \
+  EXTINSN2OPF(NAME, CPU, CLASS, SCLASS, MOP, SOP, FLAGS_F)
+
+/* Macro to generate 3 operand extesion instruction.  */
+#define EXTINSN3OP(NAME, CPU, CLASS, SCLASS, MOP, SOP)			\
+  { NAME, INSN3OP_ABC (MOP,SOP),  MINSN3OP_ABC,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RARBRC,     FLAGS_F },					\
+  { NAME, INSN3OP_0BC (MOP,SOP),  MINSN3OP_0BC,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZARBRC,     FLAGS_F   },				\
+  { NAME, INSN3OP_CBBC (MOP,SOP), MINSN3OP_CBBC, CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RBRBRC,     FLAGS_CCF },				\
+  { NAME, INSN3OP_ABU (MOP,SOP),  MINSN3OP_ABU,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RARBU6,     FLAGS_F   },				\
+  { NAME, INSN3OP_0BU (MOP,SOP),  MINSN3OP_0BU,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZARBU6,     FLAGS_F   },				\
+  { NAME, INSN3OP_CBBU (MOP,SOP), MINSN3OP_CBBU, CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RBRBU6,     FLAGS_CCF },				\
+  { NAME, INSN3OP_BBS (MOP,SOP),  MINSN3OP_BBS,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RBRBS12,    FLAGS_F   },				\
+  { NAME, INSN3OP_ALC (MOP,SOP),  MINSN3OP_ALC,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RALIMMRC,   FLAGS_F   },				\
+  { NAME, INSN3OP_ABL (MOP,SOP),  MINSN3OP_ABL,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RARBLIMM,   FLAGS_F   },				\
+  { NAME, INSN3OP_0LC (MOP,SOP),  MINSN3OP_0LC,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMRC,   FLAGS_F   },				\
+  { NAME, INSN3OP_0BL (MOP,SOP),  MINSN3OP_0BL,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZARBLIMM,   FLAGS_F   },				\
+  { NAME, INSN3OP_C0LC (MOP,SOP), MINSN3OP_C0LC, CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMRC,   FLAGS_CCF },				\
+  { NAME, INSN3OP_CBBL (MOP,SOP), MINSN3OP_CBBL, CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RBRBLIMM,   FLAGS_CCF },				\
+  { NAME, INSN3OP_ALU (MOP,SOP),  MINSN3OP_ALU,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RALIMMU6,   FLAGS_F   },				\
+  { NAME, INSN3OP_0LU (MOP,SOP),  MINSN3OP_0LU,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMU6,   FLAGS_F   },				\
+  { NAME, INSN3OP_C0LU (MOP,SOP), MINSN3OP_C0LU, CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMU6,   FLAGS_CCF },				\
+  { NAME, INSN3OP_0LS (MOP,SOP),  MINSN3OP_0LS,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMS12,  FLAGS_F   },				\
+  { NAME, INSN3OP_ALL (MOP,SOP),  MINSN3OP_ALL,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_RALIMMLIMM, FLAGS_F   },				\
+  { NAME, INSN3OP_0LL (MOP,SOP),  MINSN3OP_0LL,  CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMLIMM, FLAGS_F   },				\
+  { NAME, INSN3OP_C0LL (MOP,SOP), MINSN3OP_C0LL, CPU, CLASS, SCLASS,	\
+      ARG_32BIT_ZALIMMLIMM, FLAGS_CCF },
+
+/* Extension instruction declarations.  */
+EXTINSN2OP ("dsp_fp_flt2i",  ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE1, 7, 43)
+EXTINSN2OP ("dsp_fp_i2flt",  ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE1, 7, 44)
+EXTINSN2OP ("dsp_fp_sqrt",   ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE2, 7, 45)
+
+EXTINSN3OP ("dsp_fp_div", ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE2, 7, 42)
+EXTINSN3OP ("dsp_fp_cmp", ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE1, 7, 43)
diff --git a/opcodes/arc-flag-classes.def b/opcodes/arc-flag-classes.def
deleted file mode 100644
index bb33d033b58..00000000000
--- a/opcodes/arc-flag-classes.def
+++ /dev/null
@@ -1,125 +0,0 @@
-/* ARC flag class defintions.
-   Copyright (C) 2023 Free Software Foundation, Inc.
-
-   Contributed by Claudiu Zissulescu (claziss@synopsys.com)
-   Refactored by Cupertino Miranda (cmiranda@synopsys.com)
-
-   This file is part of libopcodes.
-
-   This library is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   It is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-   License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-FLAG_CLASS(EMPTY, F_CLASS_NONE, 0, 0, F_NULL)
-FLAG_CLASS(CC_EQ, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0 , F_EQUAL)
-FLAG_CLASS(CC_GE, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0 , F_GE)
-FLAG_CLASS(CC_GT, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_GT)
-FLAG_CLASS(CC_HI, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_HI)
-FLAG_CLASS(CC_HS, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_NOTCARRY)
-FLAG_CLASS(CC_LE, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_LE)
-FLAG_CLASS(CC_LO, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_CARRY)
-FLAG_CLASS(CC_LS, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_LS)
-FLAG_CLASS(CC_LT, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_LT)
-FLAG_CLASS(CC_NE, F_CLASS_IMPLICIT | F_CLASS_COND, 0, 0, F_NOTEQUAL)
-
-FLAG_CLASS(AA_AB, F_CLASS_IMPLICIT | F_CLASS_WB, 0, 0, F_AB3)
-FLAG_CLASS(AA_AW, F_CLASS_IMPLICIT | F_CLASS_WB, 0, 0, F_AW3)
-
-FLAG_CLASS(ZZ_D, F_CLASS_IMPLICIT | F_CLASS_ZZ, 0, 0, F_SIZED)
-FLAG_CLASS(ZZ_L, F_CLASS_IMPLICIT | F_CLASS_ZZ, 0, 0, F_SIZEL)
-FLAG_CLASS(ZZ_W, F_CLASS_IMPLICIT | F_CLASS_ZZ, 0, 0, F_SIZEW)
-FLAG_CLASS(ZZ_H, F_CLASS_IMPLICIT | F_CLASS_ZZ, 0, 0, F_H1)
-FLAG_CLASS(ZZ_B, F_CLASS_IMPLICIT | F_CLASS_ZZ, 0, 0, F_SIZEB1)
-
-FLAG_CLASS(CC, F_CLASS_OPTIONAL | F_CLASS_EXTEND | F_CLASS_COND, 0, 0, F_ALWAYS, F_RA, F_EQUAL, F_ZERO, F_NOTEQUAL, F_NOTZERO, F_POZITIVE, F_PL, F_NEGATIVE, F_MINUS, F_CARRY, F_CARRYSET, F_LOWER, F_CARRYCLR, F_NOTCARRY, F_HIGHER, F_OVERFLOWSET, F_OVERFLOW, F_NOTOVERFLOW, F_OVERFLOWCLR, F_GT, F_GE, F_LT, F_LE, F_HI, F_LS, F_PNZ, F_NJ, F_NM, F_NO_T)
-
-FLAG_CLASS(AA_ADDR3, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A3, F_AW3, F_AB3, F_AS3)
-FLAG_CLASS(AA27, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A3, F_AW3, F_AB3, F_AS3)
-FLAG_CLASS(AS27, F_CLASS_OPTIONAL, 0, 0, F_AS3)
-FLAG_CLASS(AA_ADDR9, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A9, F_AW9, F_AB9, F_AS9)
-FLAG_CLASS(AA21, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A9, F_AW9, F_AB9, F_AS9)
-FLAG_CLASS(AAB21, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A9, F_AW9, F_AB9)
-FLAG_CLASS(AA_ADDR22, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A22, F_AW22, F_AB22, F_AS22)
-FLAG_CLASS(AA8, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A22, F_AW22, F_AB22, F_AS22)
-FLAG_CLASS(AAB8, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_A22, F_AW22, F_AB22)
-
-FLAG_CLASS(F, F_CLASS_OPTIONAL, 0, 0, F_FLAG)
-FLAG_CLASS(FHARD, F_CLASS_OPTIONAL, 0, 0, F_FFAKE)
-
-FLAG_CLASS(RL, F_CLASS_OPTIONAL, 0, 0, F_RL)
-FLAG_CLASS(AQ, F_CLASS_OPTIONAL, 0, 0, F_AQ)
-
-FLAG_CLASS(ATOP, F_CLASS_REQUIRED, 0, 0, F_ATO_ADD, F_ATO_OR, F_ATO_AND, F_ATO_XOR, F_ATO_MINU, F_ATO_MAXU, F_ATO_MIN, F_ATO_MAX)
-
-FLAG_CLASS(T, F_CLASS_OPTIONAL, 0, 0, F_NT, F_T)
-FLAG_CLASS(D, F_CLASS_OPTIONAL, 0, 0, F_ND, F_D)
-FLAG_CLASS(DNZ_D, F_CLASS_OPTIONAL, 0, 0, F_DNZ_ND, F_DNZ_D)
-
-FLAG_CLASS(DHARD, F_CLASS_OPTIONAL, 0, 0, F_DFAKE)
-
-FLAG_CLASS(DI20, F_CLASS_OPTIONAL, 0, 0, F_DI11)
-FLAG_CLASS(DI14, F_CLASS_OPTIONAL, 0, 0, F_DI14)
-FLAG_CLASS(DI16, F_CLASS_OPTIONAL, 0, 0, F_DI15)
-FLAG_CLASS(DI26, F_CLASS_OPTIONAL, 0, 0, F_DI5)
-
-FLAG_CLASS(X25, F_CLASS_OPTIONAL, 0, 0, F_SIGN6)
-FLAG_CLASS(X15, F_CLASS_OPTIONAL, 0, 0, F_SIGN16)
-FLAG_CLASS(XHARD, F_CLASS_OPTIONAL, 0, 0, F_SIGNX)
-FLAG_CLASS(X, F_CLASS_OPTIONAL, 0, 0, F_SIGNX)
-
-FLAG_CLASS(ZZ13, F_CLASS_OPTIONAL, 0, 0, F_SIZEB17, F_SIZEW17, F_H17)
-FLAG_CLASS(ZZ23, F_CLASS_OPTIONAL, 0, 0, F_SIZEB7, F_SIZEW7, F_H7)
-FLAG_CLASS(ZZ29, F_CLASS_OPTIONAL, 0, 0, F_SIZEB1, F_SIZEW1, F_H1)
-FLAG_CLASS(ZZW6, F_CLASS_OPTIONAL, 0, 0, F_SIZEB1)
-FLAG_CLASS(ZZH1, F_CLASS_OPTIONAL, 0, 0, F_SIZEW1, F_H1)
-
-FLAG_CLASS(AS, F_CLASS_OPTIONAL, 0, 0, F_ASFAKE)
-FLAG_CLASS(AAHARD13, F_CLASS_OPTIONAL, 0, 0, F_ASFAKE)
-FLAG_CLASS(NE, F_CLASS_REQUIRED, 0, 0, F_NE)
-
-/* ARC NPS400 Support: See comment near head of file.  */
-FLAG_CLASS(NPS_CL, F_CLASS_REQUIRED, 0, 0, F_NPS_CL)
-FLAG_CLASS(NPS_NA, F_CLASS_OPTIONAL, 0, 0, F_NPS_NA)
-FLAG_CLASS(NPS_SR, F_CLASS_OPTIONAL, 0, 0, F_NPS_SR)
-FLAG_CLASS(NPS_M, F_CLASS_OPTIONAL, 0, 0, F_NPS_M)
-FLAG_CLASS(NPS_F, F_CLASS_OPTIONAL, 0, 0, F_NPS_FLAG)
-FLAG_CLASS(NPS_R, F_CLASS_OPTIONAL, 0, 0, F_NPS_R)
-FLAG_CLASS(NPS_SCHD_RW, F_CLASS_REQUIRED, 0, 0, F_NPS_RW, F_NPS_RD)
-FLAG_CLASS(NPS_SCHD_TRIG, F_CLASS_REQUIRED, 0, 0, F_NPS_WFT)
-FLAG_CLASS(NPS_SCHD_IE, F_CLASS_OPTIONAL, 0, 0, F_NPS_IE1, F_NPS_IE2, F_NPS_IE12)
-FLAG_CLASS(NPS_SYNC, F_CLASS_REQUIRED, 0, 0, F_NPS_SYNC_RD, F_NPS_SYNC_WR)
-FLAG_CLASS(NPS_HWS_OFF, F_CLASS_REQUIRED, 0, 0, F_NPS_HWS_OFF)
-FLAG_CLASS(NPS_HWS_RESTORE, F_CLASS_REQUIRED, 0, 0, F_NPS_HWS_RESTORE)
-FLAG_CLASS(NPS_SX, F_CLASS_OPTIONAL, 0, 0, F_NPS_SX)
-FLAG_CLASS(NPS_AR_AL, F_CLASS_REQUIRED, 0, 0, F_NPS_AR, F_NPS_AL)
-FLAG_CLASS(NPS_S, F_CLASS_REQUIRED, 0, 0, F_NPS_S)
-FLAG_CLASS(NPS_ZNCV, F_CLASS_REQUIRED, 0, 0, F_NPS_ZNCV_RD, F_NPS_ZNCV_WR)
-FLAG_CLASS(NPS_P0, F_CLASS_REQUIRED, 0, 0, F_NPS_P0)
-FLAG_CLASS(NPS_P1, F_CLASS_REQUIRED, 0, 0, F_NPS_P1)
-FLAG_CLASS(NPS_P2, F_CLASS_REQUIRED, 0, 0, F_NPS_P2)
-FLAG_CLASS(NPS_P3, F_CLASS_REQUIRED, 0, 0, F_NPS_P3)
-FLAG_CLASS(NPS_LDBIT_DI, F_CLASS_REQUIRED, 0, 0, F_NPS_LDBIT_DI)
-FLAG_CLASS(NPS_LDBIT_CL1, F_CLASS_OPTIONAL, 0, 0, F_NPS_LDBIT_CL1)
-FLAG_CLASS(NPS_LDBIT_CL2, F_CLASS_OPTIONAL, 0, 0, F_NPS_LDBIT_CL2)
-FLAG_CLASS(NPS_LDBIT_X_1, F_CLASS_OPTIONAL, 0, 0, F_NPS_LDBIT_X2_1, F_NPS_LDBIT_X4_1)
-FLAG_CLASS(NPS_LDBIT_X_2, F_CLASS_OPTIONAL, 0, 0, F_NPS_LDBIT_X2_2, F_NPS_LDBIT_X4_2)
-FLAG_CLASS(NPS_CORE, F_CLASS_REQUIRED, 0, 0, F_NPS_CORE)
-FLAG_CLASS(NPS_CLSR, F_CLASS_REQUIRED, 0, 0, F_NPS_CLSR)
-FLAG_CLASS(NPS_ALL, F_CLASS_REQUIRED, 0, 0, F_NPS_ALL)
-FLAG_CLASS(NPS_GIC, F_CLASS_REQUIRED, 0, 0, F_NPS_GIC)
-FLAG_CLASS(NPS_RSPI_GIC, F_CLASS_REQUIRED, 0, 0, F_NPS_RSPI_GIC)
-FLAG_CLASS(FPCC, F_CLASS_OPTIONAL | F_CLASS_EXTEND | F_CLASS_COND, insert_fs2, extract_fs2, F_ALWAYS, F_RA, F_EQUAL, F_ZERO, F_NOTEQUAL, F_NOTZERO, F_POZITIVE, F_PL, F_NEGATIVE, F_MINUS, F_CARRY, F_CARRYSET, F_LOWER, F_CARRYCLR, F_NOTCARRY, F_HIGHER, F_OVERFLOWSET, F_OVERFLOW, F_NOTOVERFLOW, F_OVERFLOWCLR, F_GT, F_GE, F_LT, F_LE, F_HI, F_LS, F_PNZ, F_NJ, F_NM, F_NO_T)
-FLAG_CLASS(AA_128, F_CLASS_OPTIONAL | F_CLASS_WB, 0, 0, F_AA128, F_AA128W, F_AA128B, F_AA128S)
-FLAG_CLASS(AS_128, F_CLASS_OPTIONAL, 0, 0, F_AA128S)
-FLAG_CLASS(AA_128S, F_CLASS_OPTIONAL | F_CLASS_WB, insert_qq, extract_qq, F_AA128, F_AA128W, F_AA128B, F_AA128S)
-FLAG_CLASS(AS_128S, F_CLASS_OPTIONAL, insert_qq, extract_qq, F_AA128S)
diff --git a/opcodes/arc-flag.def b/opcodes/arc-flag.def
deleted file mode 100644
index 1312c464a3c..00000000000
--- a/opcodes/arc-flag.def
+++ /dev/null
@@ -1,179 +0,0 @@
-/* ARC flag defintions.
-   Copyright (C) 2023 Free Software Foundation, Inc.
-
-   Contributed by Claudiu Zissulescu (claziss@synopsys.com)
-   Refactored by Cupertino Miranda (cmiranda@synopsys.com)
-
-   This file is part of libopcodes.
-
-   This library is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   It is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-   License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-FLAG(ALWAYS, "al", 0, 0, 0, 0)
-FLAG(RA, "ra", 0, 0, 0, 0)
-FLAG(EQUAL, "eq", 1, 5, 0, 1)
-FLAG(ZERO, "z", 1, 5, 0, 0)
-FLAG(NOTEQUAL, "ne", 2, 5, 0, 1)
-FLAG(NOTZERO, "nz", 2, 5, 0, 0)
-FLAG(POZITIVE, "p", 3, 5, 0, 1)
-FLAG(PL, "pl", 3, 5, 0, 0)
-FLAG(NEGATIVE, "n", 4, 5, 0, 1)
-FLAG(MINUS, "mi", 4, 5, 0, 0)
-FLAG(CARRY, "c", 5, 5, 0, 1)
-FLAG(CARRYSET, "cs", 5, 5, 0, 0)
-FLAG(LOWER, "lo", 5, 5, 0, 0)
-FLAG(CARRYCLR, "cc", 6, 5, 0, 0)
-FLAG(NOTCARRY, "nc", 6, 5, 0, 1)
-FLAG(HIGHER, "hs", 6, 5, 0, 0)
-FLAG(OVERFLOWSET, "vs", 7, 5, 0, 0)
-FLAG(OVERFLOW, "v", 7, 5, 0, 1)
-FLAG(NOTOVERFLOW, "nv", 8, 5, 0, 1)
-FLAG(OVERFLOWCLR, "vc", 8, 5, 0, 0)
-FLAG(GT, "gt", 9, 5, 0, 1)
-FLAG(GE, "ge", 10, 5, 0, 1)
-FLAG(LT, "lt", 11, 5, 0, 1)
-FLAG(LE, "le", 12, 5, 0, 1)
-FLAG(HI, "hi", 13, 5, 0, 1)
-FLAG(LS, "ls", 14, 5, 0, 1)
-FLAG(PNZ, "pnz", 15, 5, 0, 1)
-FLAG(NJ, "nj", 21, 5, 0, 1)
-FLAG(NM, "nm", 23, 5, 0, 1)
-FLAG(NO_T, "nt", 24, 5, 0, 1)
-
-  /* FLAG.  */
-FLAG(FLAG, "f", 1, 1, 15, 1)
-FLAG(FFAKE, "f", 0, 0, 0, 1)
-FLAG(AQ, "aq", 1, 1, 15, 1)
-FLAG(RL, "rl", 1, 1, 15, 1)
-
-  /* Atomic operations.  */
-FLAG(ATO_ADD, "add", 0, 3, 0, 1)
-FLAG(ATO_OR, "or", 1, 3, 0, 1)
-FLAG(ATO_AND, "and", 2, 3, 0, 1)
-FLAG(ATO_XOR, "xor", 3, 3, 0, 1)
-FLAG(ATO_MINU, "minu", 4, 3, 0, 1)
-FLAG(ATO_MAXU, "maxu", 5, 3, 0, 1)
-FLAG(ATO_MIN, "min", 6, 3, 0, 1)
-FLAG(ATO_MAX, "max", 7, 3, 0, 1)
-
-  /* Delay slot.  */
-FLAG(ND, "nd", 0, 1, 5, 0)
-FLAG(D, "d", 1, 1, 5, 1)
-FLAG(DFAKE, "d", 0, 0, 0, 1)
-FLAG(DNZ_ND, "nd", 0, 1, 16, 0)
-FLAG(DNZ_D, "d", 1, 1, 16, 1)
-
-  /* Data size.  */
-FLAG(SIZEB1, "b", 1, 2, 1, 1)
-FLAG(SIZEB7, "b", 1, 2, 7, 1)
-FLAG(SIZEB17, "b", 1, 2, 17, 1)
-FLAG(SIZEW1, "w", 2, 2, 1, 0)
-FLAG(SIZEW7, "w", 2, 2, 7, 0)
-FLAG(SIZEW17, "w", 2, 2, 17, 0)
-
-  /* Sign extension.  */
-FLAG(SIGN6, "x", 1, 1, 6, 1)
-FLAG(SIGN16, "x", 1, 1, 16, 1)
-FLAG(SIGNX, "x", 0, 0, 0, 1)
-
-  /* Address write-back modes.  */
-FLAG(A3, "a", 1, 2, 3, 0)
-FLAG(A9, "a", 1, 2, 9, 0)
-FLAG(A22, "a", 1, 2, 22, 0)
-FLAG(AW3, "aw", 1, 2, 3, 1)
-FLAG(AW9, "aw", 1, 2, 9, 1)
-FLAG(AW22, "aw", 1, 2, 22, 1)
-FLAG(AB3, "ab", 2, 2, 3, 1)
-FLAG(AB9, "ab", 2, 2, 9, 1)
-FLAG(AB22, "ab", 2, 2, 22, 1)
-FLAG(AS3, "as", 3, 2, 3, 1)
-FLAG(AS9, "as", 3, 2, 9, 1)
-FLAG(AS22, "as", 3, 2, 22, 1)
-FLAG(ASFAKE, "as", 0, 0, 0, 1)
-
-/* address writebacks for 128-bit loads.
-   ,---.---.----------.
-   | X | D | mnemonic |
-   |---+---+----------|
-   | 0 | 0 | none     |
-   | 0 | 1 | as       |
-   | 1 | 0 | a/aw     |
-   | 1 | 1 | ab       |
-   `---^---^----------'  */
-FLAG(AA128, "a", 2, 2, 15, 0)
-FLAG(AA128W, "aw", 2, 2, 15, 1)
-FLAG(AA128B, "ab", 3, 2, 15, 1)
-FLAG(AA128S, "as", 1, 2, 15, 1)
-
-  /* Cache bypass.  */
-FLAG(DI5, "di", 1, 1, 5, 1)
-FLAG(DI11, "di", 1, 1, 11, 1)
-FLAG(DI14, "di", 1, 1, 14, 1)
-FLAG(DI15, "di", 1, 1, 15, 1)
-
-  /* ARCv2 specific.  */
-FLAG(NT, "nt", 0, 1, 3, 1)
-FLAG(T, "t", 1, 1, 3, 1)
-FLAG(H1, "h", 2, 2, 1, 1)
-FLAG(H7, "h", 2, 2, 7, 1)
-FLAG(H17, "h", 2, 2, 17, 1)
-/* Fake */
-FLAG(SIZED, "dd", 8, 0, 0, 0)
-/* Fake */
-FLAG(SIZEL, "dl", 8, 0, 0, 0)
-/* Fake */
-FLAG(SIZEW, "xx", 4, 0, 0, 0)
-
-  /* Fake Flags.  */
-FLAG(NE, "ne", 0, 0, 0, 1)
-
-/* ARC NPS400 Support: See comment near head of arcxx-opc.inc file.  */
-FLAG(NPS_CL, "cl", 0, 0, 0, 1)
-FLAG(NPS_NA, "na", 1, 1, 9, 1)
-FLAG(NPS_SR, "s", 1, 1, 13, 1)
-FLAG(NPS_M, "m", 1, 1, 7, 1)
-FLAG(NPS_FLAG, "f", 1, 1, 20, 1)
-FLAG(NPS_R, "r", 1, 1, 15, 1)
-FLAG(NPS_RW, "rw", 0, 1, 7, 1)
-FLAG(NPS_RD, "rd", 1, 1, 7, 1)
-FLAG(NPS_WFT, "wft", 0, 0, 0, 1)
-FLAG(NPS_IE1, "ie1", 1, 2, 8, 1)
-FLAG(NPS_IE2, "ie2", 2, 2, 8, 1)
-FLAG(NPS_IE12, "ie12", 3, 2, 8, 1)
-FLAG(NPS_SYNC_RD, "rd", 0, 1, 6, 1)
-FLAG(NPS_SYNC_WR, "wr", 1, 1, 6, 1)
-FLAG(NPS_HWS_OFF, "off", 0, 0, 0, 1)
-FLAG(NPS_HWS_RESTORE, "restore", 0, 0, 0, 1)
-FLAG(NPS_SX, "sx", 1, 1, 14, 1)
-FLAG(NPS_AR, "ar", 0, 1, 0, 1)
-FLAG(NPS_AL, "al", 1, 1, 0, 1)
-FLAG(NPS_S, "s", 0, 0, 0, 1)
-FLAG(NPS_ZNCV_RD, "rd", 0, 1, 15, 1)
-FLAG(NPS_ZNCV_WR, "wr", 1, 1, 15, 1)
-FLAG(NPS_P0, "p0", 0, 0, 0, 1)
-FLAG(NPS_P1, "p1", 0, 0, 0, 1)
-FLAG(NPS_P2, "p2", 0, 0, 0, 1)
-FLAG(NPS_P3, "p3", 0, 0, 0, 1)
-FLAG(NPS_LDBIT_DI, "di", 0, 0, 0, 1)
-FLAG(NPS_LDBIT_CL1, "cl", 1, 1, 6, 1)
-FLAG(NPS_LDBIT_CL2, "cl", 1, 1, 16, 1)
-FLAG(NPS_LDBIT_X2_1, "x2", 1, 2, 9, 1)
-FLAG(NPS_LDBIT_X2_2, "x2", 1, 2, 22, 1)
-FLAG(NPS_LDBIT_X4_1, "x4", 2, 2, 9, 1)
-FLAG(NPS_LDBIT_X4_2, "x4", 2, 2, 22, 1)
-FLAG(NPS_CORE, "core", 1, 3, 6, 1)
-FLAG(NPS_CLSR, "clsr", 2, 3, 6, 1)
-FLAG(NPS_ALL, "all", 3, 3, 6, 1)
-FLAG(NPS_GIC, "gic", 4, 3, 6, 1)
-FLAG(NPS_RSPI_GIC, "gic", 5, 3, 6, 1)
diff --git a/opcodes/arc-fxi.h b/opcodes/arc-fxi.h
index d87e7755f20..e2d4de6a579 100644
--- a/opcodes/arc-fxi.h
+++ b/opcodes/arc-fxi.h
@@ -1318,63 +1318,3 @@ extract_uimm6_axx_ (unsigned long long insn ATTRIBUTE_UNUSED,
   return value;
 }
 #endif /* EXTRACT_UIMM6_AXX_ */
-
-/* mask  = 0000022000011111.  */
-#ifndef INSERT_UIMM9_A32_11_S
-#define INSERT_UIMM9_A32_11_S
-ATTRIBUTE_UNUSED static unsigned long long
-insert_uimm9_a32_11_s (unsigned long long insn ATTRIBUTE_UNUSED,
-		       long long int value ATTRIBUTE_UNUSED,
-		       const char **errmsg ATTRIBUTE_UNUSED)
-{
-  if (value & 0x03)
-    *errmsg = "Target address is not 32bit aligned.";
-
-  insn |= ((value >> 2) & 0x001f) << 0;
-  insn |= ((value >> 7) & 0x0003) << 9;
-  return insn;
-}
-#endif /* INSERT_UIMM9_A32_11_S.  */
-
-#ifndef EXTRACT_UIMM9_A32_11_S
-#define EXTRACT_UIMM9_A32_11_S
-ATTRIBUTE_UNUSED static long long int
-extract_uimm9_a32_11_s (unsigned long long insn ATTRIBUTE_UNUSED,
-			bool *invalid ATTRIBUTE_UNUSED)
-{
-  unsigned value = 0;
-  value |= ((insn >> 0) & 0x001f) << 2;
-  value |= ((insn >> 9) & 0x0003) << 7;
-
-  return value;
-}
-#endif /* EXTRACT_UIMM9_A32_11_S.  */
-
-/* mask  = 0000022222220111.  */
-#ifndef INSERT_UIMM10_13_S
-#define INSERT_UIMM10_13_S
-ATTRIBUTE_UNUSED static unsigned long long
-insert_uimm10_13_s (unsigned long long insn ATTRIBUTE_UNUSED,
-		    long long int value ATTRIBUTE_UNUSED,
-		    const char **errmsg ATTRIBUTE_UNUSED)
-{
-  insn |= ((value >> 0) & 0x0007) << 0;
-  insn |= ((value >> 3) & 0x007f) << 4;
-
-  return insn;
-}
-#endif /* INSERT_UIMM10_13_S.  */
-
-#ifndef EXTRACT_UIMM10_13_S
-#define EXTRACT_UIMM10_13_S
-ATTRIBUTE_UNUSED static long long int
-extract_uimm10_13_s (unsigned long long insn ATTRIBUTE_UNUSED,
-		     bool *invalid ATTRIBUTE_UNUSED)
-{
-  unsigned value = 0;
-  value |= ((insn >> 0) & 0x0007) << 0;
-  value |= ((insn >> 4) & 0x007f) << 3;
-
-  return value;
-}
-#endif /* EXTRACT_UIMM10_13_S.  */
diff --git a/opcodes/arc-opc.c b/opcodes/arc-opc.c
index 8e7c910a18c..4257e79fe4b 100644
--- a/opcodes/arc-opc.c
+++ b/opcodes/arc-opc.c
@@ -19,103 +19,2595 @@
    along with this program; if not, write to the Free Software Foundation,
    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-#include "arcxx-opc.inc"
-
-/* Common combinations of FLAGS.  */
-#define FLAGS_NONE { 0 }
-#define FLAGS_F    { C_F }
-#define FLAGS_CC   { C_CC }
-#define FLAGS_CCF  { C_CC, C_F }
-
-/* Common combination of arguments.  */
-#define ARG_NONE		{ 0 }
-#define ARG_32BIT_RARBRC	{ RA, RB, RC }
-#define ARG_32BIT_ZARBRC	{ ZA, RB, RC }
-#define ARG_32BIT_RBRBRC	{ RB, RBdup, RC }
-#define ARG_32BIT_RARBU6	{ RA, RB, UIMM6_20 }
-#define ARG_32BIT_ZARBU6	{ ZA, RB, UIMM6_20 }
-#define ARG_32BIT_RBRBU6	{ RB, RBdup, UIMM6_20 }
-#define ARG_32BIT_RBRBS12	{ RB, RBdup, SIMM12_20 }
-#define ARG_32BIT_RALIMMRC	{ RA, LIMM, RC }
-#define ARG_32BIT_RARBLIMM	{ RA, RB, LIMM }
-#define ARG_32BIT_ZALIMMRC	{ ZA, LIMM, RC }
-#define ARG_32BIT_ZARBLIMM	{ ZA, RB, LIMM }
-
-#define ARG_32BIT_RBRBLIMM	{ RB, RBdup, LIMM }
-#define ARG_32BIT_RALIMMU6	{ RA, LIMM, UIMM6_20 }
-#define ARG_32BIT_ZALIMMU6	{ ZA, LIMM, UIMM6_20 }
-
-#define ARG_32BIT_ZALIMMS12	{ ZA, LIMM, SIMM12_20 }
-#define ARG_32BIT_RALIMMLIMM	{ RA, LIMM, LIMMdup }
-#define ARG_32BIT_ZALIMMLIMM	{ ZA, LIMM, LIMMdup }
-
-#define ARG_32BIT_RBRC   { RB, RC }
-#define ARG_32BIT_ZARC   { ZA, RC }
-#define ARG_32BIT_RBU6   { RB, UIMM6_20 }
-#define ARG_32BIT_ZAU6   { ZA, UIMM6_20 }
-#define ARG_32BIT_RBLIMM { RB, LIMM }
-#define ARG_32BIT_ZALIMM { ZA, LIMM }
-
-/* Macro to generate 2 operand extension instruction.  */
-#define EXTINSN2OPF(NAME, CPU, CLASS, SCLASS, MOP, SOP, FL)	 \
-  { NAME, INSN2OP_BC (MOP,SOP), MINSN2OP_BC, CPU, CLASS, SCLASS, \
-      ARG_32BIT_RBRC,   FL },					 \
-  { NAME, INSN2OP_0C (MOP,SOP), MINSN2OP_0C, CPU, CLASS, SCLASS, \
-      ARG_32BIT_ZARC,   FL },					 \
-  { NAME, INSN2OP_BU (MOP,SOP), MINSN2OP_BU, CPU, CLASS, SCLASS, \
-      ARG_32BIT_RBU6,   FL },					 \
-  { NAME, INSN2OP_0U (MOP,SOP), MINSN2OP_0U, CPU, CLASS, SCLASS, \
-      ARG_32BIT_ZAU6,   FL },					 \
-  { NAME, INSN2OP_BL (MOP,SOP), MINSN2OP_BL, CPU, CLASS, SCLASS, \
-      ARG_32BIT_RBLIMM, FL },					 \
-  { NAME, INSN2OP_0L (MOP,SOP), MINSN2OP_0L, CPU, CLASS, SCLASS, \
-      ARG_32BIT_ZALIMM, FL },
-
-#define EXTINSN2OP(NAME, CPU, CLASS, SCLASS, MOP, SOP)		 \
-  EXTINSN2OPF (NAME, CPU, CLASS, SCLASS, MOP, SOP, FLAGS_F)
-
-/* Macro to generate 3 operand extesion instruction.  */
-#define EXTINSN3OP(NAME, CPU, CLASS, SCLASS, MOP, SOP)			\
-  { NAME, INSN3OP_ABC (MOP,SOP),  MINSN3OP_ABC,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RARBRC,     FLAGS_F },					\
-  { NAME, INSN3OP_0BC (MOP,SOP),  MINSN3OP_0BC,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZARBRC,     FLAGS_F   },				\
-  { NAME, INSN3OP_CBBC (MOP,SOP), MINSN3OP_CBBC, CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RBRBRC,     FLAGS_CCF },				\
-  { NAME, INSN3OP_ABU (MOP,SOP),  MINSN3OP_ABU,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RARBU6,     FLAGS_F   },				\
-  { NAME, INSN3OP_0BU (MOP,SOP),  MINSN3OP_0BU,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZARBU6,     FLAGS_F   },				\
-  { NAME, INSN3OP_CBBU (MOP,SOP), MINSN3OP_CBBU, CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RBRBU6,     FLAGS_CCF },				\
-  { NAME, INSN3OP_BBS (MOP,SOP),  MINSN3OP_BBS,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RBRBS12,    FLAGS_F   },				\
-  { NAME, INSN3OP_ALC (MOP,SOP),  MINSN3OP_ALC,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RALIMMRC,   FLAGS_F   },				\
-  { NAME, INSN3OP_ABL (MOP,SOP),  MINSN3OP_ABL,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RARBLIMM,   FLAGS_F   },				\
-  { NAME, INSN3OP_0LC (MOP,SOP),  MINSN3OP_0LC,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMRC,   FLAGS_F   },				\
-  { NAME, INSN3OP_0BL (MOP,SOP),  MINSN3OP_0BL,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZARBLIMM,   FLAGS_F   },				\
-  { NAME, INSN3OP_C0LC (MOP,SOP), MINSN3OP_C0LC, CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMRC,   FLAGS_CCF },				\
-  { NAME, INSN3OP_CBBL (MOP,SOP), MINSN3OP_CBBL, CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RBRBLIMM,   FLAGS_CCF },				\
-  { NAME, INSN3OP_ALU (MOP,SOP),  MINSN3OP_ALU,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RALIMMU6,   FLAGS_F   },				\
-  { NAME, INSN3OP_0LU (MOP,SOP),  MINSN3OP_0LU,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMU6,   FLAGS_F   },				\
-  { NAME, INSN3OP_C0LU (MOP,SOP), MINSN3OP_C0LU, CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMU6,   FLAGS_CCF },				\
-  { NAME, INSN3OP_0LS (MOP,SOP),  MINSN3OP_0LS,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMS12,  FLAGS_F   },				\
-  { NAME, INSN3OP_ALL (MOP,SOP),  MINSN3OP_ALL,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_RALIMMLIMM, FLAGS_F   },				\
-  { NAME, INSN3OP_0LL (MOP,SOP),  MINSN3OP_0LL,  CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMLIMM, FLAGS_F   },				\
-  { NAME, INSN3OP_C0LL (MOP,SOP), MINSN3OP_C0LL, CPU, CLASS, SCLASS,	\
-      ARG_32BIT_ZALIMMLIMM, FLAGS_CCF },
+#include "sysdep.h"
+#include <stdio.h>
+#include "bfd.h"
+#include "opcode/arc.h"
+#include "opintl.h"
+#include "libiberty.h"
+
+/* ARC NPS400 Support: The ARC NPS400 core is an ARC700 with some custom
+   instructions. All NPS400 features are built into all ARC target builds as
+   this reduces the chances that regressions might creep in.  */
+
+/* Insert RA register into a 32-bit opcode, with checks.  */
+
+static unsigned long long
+insert_ra_chk (unsigned long long  insn,
+	       long long           value,
+	       const char **       errmsg)
+{
+  if (value == 60)
+    *errmsg = _("LP_COUNT register cannot be used as destination register");
+
+  return insn | (value & 0x3F);
+}
+
+/* Insert RB register into a 32-bit opcode.  */
+
+static unsigned long long
+insert_rb (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  return insn | ((value & 0x07) << 24) | (((value >> 3) & 0x07) << 12);
+}
+
+/* Insert RB register with checks.  */
+
+static unsigned long long
+insert_rb_chk (unsigned long long  insn,
+	       long long           value,
+	       const char **       errmsg)
+{
+  if (value == 60)
+    *errmsg = _("LP_COUNT register cannot be used as destination register");
+
+  return insn | ((value & 0x07) << 24) | (((value >> 3) & 0x07) << 12);
+}
+
+static long long
+extract_rb (unsigned long long insn,
+	    bool *invalid)
+{
+  int value = (((insn >> 12) & 0x07) << 3) | ((insn >> 24) & 0x07);
+
+  if (value == 0x3e && invalid)
+    *invalid = true; /* A limm operand, it should be extracted in a
+			different way.  */
+
+  return value;
+}
+
+static unsigned long long
+insert_rad (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  if (value & 0x01)
+    *errmsg = _("cannot use odd number destination register");
+  if (value == 60)
+    *errmsg = _("LP_COUNT register cannot be used as destination register");
+
+  return insn | (value & 0x3F);
+}
+
+static unsigned long long
+insert_rcd (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  if (value & 0x01)
+    *errmsg = _("cannot use odd number source register");
+
+  return insn | ((value & 0x3F) << 6);
+}
+
+static unsigned long long
+insert_rbd (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  if (value & 0x01)
+    *errmsg = _("cannot use odd number source register");
+  if (value == 60)
+    *errmsg = _("LP_COUNT register cannot be used as destination register");
+
+  return insn | ((value & 0x07) << 24) | (((value >> 3) & 0x07) << 12);
+}
+
+/* Dummy insert ZERO operand function.  */
+
+static unsigned long long
+insert_za (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value)
+    *errmsg = _("operand is not zero");
+  return insn;
+}
+
+/* Insert Y-bit in bbit/br instructions.  This function is called only
+   when solving fixups.  */
+
+static unsigned long long
+insert_Ybit (unsigned long long  insn,
+	     long long           value,
+	     const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  if (value > 0)
+    insn |= 0x08;
+
+  return insn;
+}
+
+/* Insert Y-bit in bbit/br instructions.  This function is called only
+   when solving fixups.  */
+
+static unsigned long long
+insert_NYbit (unsigned long long  insn,
+	      long long           value,
+	      const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  if (value < 0)
+    insn |= 0x08;
+
+  return insn;
+}
+
+/* Insert H register into a 16-bit opcode.  */
+
+static unsigned long long
+insert_rhv1 (unsigned long long  insn,
+	     long long           value,
+	     const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  return insn |= ((value & 0x07) << 5) | ((value >> 3) & 0x07);
+}
+
+static long long
+extract_rhv1 (unsigned long long insn,
+	      bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = ((insn & 0x7) << 3) | ((insn >> 5) & 0x7);
+
+  return value;
+}
+
+/* Insert H register into a 16-bit opcode.  */
+
+static unsigned long long
+insert_rhv2 (unsigned long long  insn,
+	     long long           value,
+	     const char **       errmsg)
+{
+  if (value == 0x1E)
+    *errmsg = _("register R30 is a limm indicator");
+  else if (value < 0 || value > 31)
+    *errmsg = _("register out of range");
+  return insn |= ((value & 0x07) << 5) | ((value >> 3) & 0x03);
+}
+
+static long long
+extract_rhv2 (unsigned long long insn,
+	      bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = ((insn >> 5) & 0x07) | ((insn & 0x03) << 3);
+
+  return value;
+}
+
+static unsigned long long
+insert_r0 (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value != 0)
+    *errmsg = _("register must be R0");
+  return insn;
+}
+
+static long long
+extract_r0 (unsigned long long insn ATTRIBUTE_UNUSED,
+	    bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+
+static unsigned long long
+insert_r1 (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value != 1)
+    *errmsg = _("register must be R1");
+  return insn;
+}
+
+static long long
+extract_r1 (unsigned long long insn ATTRIBUTE_UNUSED,
+	    bool* invalid ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+static unsigned long long
+insert_r2 (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value != 2)
+    *errmsg = _("register must be R2");
+  return insn;
+}
+
+static long long
+extract_r2 (unsigned long long insn ATTRIBUTE_UNUSED,
+	    bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 2;
+}
+
+static unsigned long long
+insert_r3 (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value != 3)
+    *errmsg = _("register must be R3");
+  return insn;
+}
+
+static long long
+extract_r3 (unsigned long long insn ATTRIBUTE_UNUSED,
+	    bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 3;
+}
+
+static unsigned long long
+insert_sp (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value != 28)
+    *errmsg = _("register must be SP");
+  return insn;
+}
+
+static long long
+extract_sp (unsigned long long insn ATTRIBUTE_UNUSED,
+	    bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 28;
+}
+
+static unsigned long long
+insert_gp (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg)
+{
+  if (value != 26)
+    *errmsg = _("register must be GP");
+  return insn;
+}
+
+static long long
+extract_gp (unsigned long long insn ATTRIBUTE_UNUSED,
+	    bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 26;
+}
+
+static unsigned long long
+insert_pcl (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  if (value != 63)
+    *errmsg = _("register must be PCL");
+  return insn;
+}
+
+static long long
+extract_pcl (unsigned long long insn ATTRIBUTE_UNUSED,
+	     bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 63;
+}
+
+static unsigned long long
+insert_blink (unsigned long long  insn,
+	      long long           value,
+	      const char **       errmsg)
+{
+  if (value != 31)
+    *errmsg = _("register must be BLINK");
+  return insn;
+}
+
+static long long
+extract_blink (unsigned long long insn ATTRIBUTE_UNUSED,
+	       bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 31;
+}
+
+static unsigned long long
+insert_ilink1 (unsigned long long  insn,
+	       long long           value,
+	       const char **       errmsg)
+{
+  if (value != 29)
+    *errmsg = _("register must be ILINK1");
+  return insn;
+}
+
+static long long
+extract_ilink1 (unsigned long long insn ATTRIBUTE_UNUSED,
+		bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 29;
+}
+
+static unsigned long long
+insert_ilink2 (unsigned long long  insn,
+	       long long           value,
+	       const char **       errmsg)
+{
+  if (value != 30)
+    *errmsg = _("register must be ILINK2");
+  return insn;
+}
+
+static long long
+extract_ilink2 (unsigned long long insn ATTRIBUTE_UNUSED,
+		bool *invalid ATTRIBUTE_UNUSED)
+{
+  return 30;
+}
+
+static unsigned long long
+insert_ras (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  switch (value)
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      insn |= value;
+      break;
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+      insn |= (value - 8);
+      break;
+    default:
+      *errmsg = _("register must be either r0-r3 or r12-r15");
+      break;
+    }
+  return insn;
+}
+
+static long long
+extract_ras (unsigned long long insn,
+	     bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = insn & 0x07;
+
+  if (value > 3)
+    return (value + 8);
+  else
+    return value;
+}
+
+static unsigned long long
+insert_rbs (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  switch (value)
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      insn |= value << 8;
+      break;
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+      insn |= ((value - 8)) << 8;
+      break;
+    default:
+      *errmsg = _("register must be either r0-r3 or r12-r15");
+      break;
+    }
+  return insn;
+}
+
+static long long
+extract_rbs (unsigned long long insn,
+	     bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = (insn >> 8) & 0x07;
+
+  if (value > 3)
+    return (value + 8);
+  else
+    return value;
+}
+
+static unsigned long long
+insert_rcs (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg)
+{
+  switch (value)
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      insn |= value << 5;
+      break;
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+      insn |= ((value - 8)) << 5;
+      break;
+    default:
+      *errmsg = _("register must be either r0-r3 or r12-r15");
+      break;
+    }
+  return insn;
+}
+
+static long long
+extract_rcs (unsigned long long insn,
+	     bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = (insn >> 5) & 0x07;
+
+  if (value > 3)
+    return (value + 8);
+  else
+    return value;
+}
+
+static unsigned long long
+insert_simm3s (unsigned long long  insn,
+	       long long           value,
+	       const char **       errmsg)
+{
+  int tmp = 0;
+  switch (value)
+    {
+    case -1:
+      tmp = 0x07;
+      break;
+    case 0:
+      tmp = 0x00;
+      break;
+    case 1:
+      tmp = 0x01;
+      break;
+    case 2:
+      tmp = 0x02;
+      break;
+    case 3:
+      tmp = 0x03;
+      break;
+    case 4:
+      tmp = 0x04;
+      break;
+    case 5:
+      tmp = 0x05;
+      break;
+    case 6:
+      tmp = 0x06;
+      break;
+    default:
+      *errmsg = _("accepted values are from -1 to 6");
+      break;
+    }
+
+  insn |= tmp << 8;
+  return insn;
+}
+
+static long long
+extract_simm3s (unsigned long long insn,
+		bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = (insn >> 8) & 0x07;
+
+  if (value == 7)
+    return -1;
+  else
+    return value;
+}
+
+static unsigned long long
+insert_rrange (unsigned long long  insn,
+	       long long           value,
+	       const char **       errmsg)
+{
+  int reg1 = (value >> 16) & 0xFFFF;
+  int reg2 = value & 0xFFFF;
+
+  if (reg1 != 13)
+    *errmsg = _("first register of the range should be r13");
+  else if (reg2 < 13 || reg2 > 26)
+    *errmsg = _("last register of the range doesn't fit");
+  else
+    insn |= ((reg2 - 12) & 0x0F) << 1;
+  return insn;
+}
+
+static long long
+extract_rrange (unsigned long long insn,
+		bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (insn >> 1) & 0x0F;
+}
+
+static unsigned long long
+insert_r13el (unsigned long long insn,
+	      long long int value,
+	      const char **errmsg)
+{
+  if (value != 13)
+    {
+      *errmsg = _("invalid register number, should be fp");
+      return insn;
+    }
+
+  insn |= 0x02;
+  return insn;
+}
+
+static unsigned long long
+insert_fpel (unsigned long long  insn,
+	     long long           value,
+	     const char **       errmsg)
+{
+  if (value != 27)
+    {
+      *errmsg = _("invalid register number, should be fp");
+      return insn;
+    }
+
+  insn |= 0x0100;
+  return insn;
+}
+
+static long long
+extract_fpel (unsigned long long insn,
+	      bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (insn & 0x0100) ? 27 : -1;
+}
+
+static unsigned long long
+insert_blinkel (unsigned long long  insn,
+		long long           value,
+		const char **       errmsg)
+{
+  if (value != 31)
+    {
+      *errmsg = _("invalid register number, should be blink");
+      return insn;
+    }
+
+  insn |= 0x0200;
+  return insn;
+}
+
+static long long
+extract_blinkel (unsigned long long insn,
+		 bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (insn & 0x0200) ? 31 : -1;
+}
+
+static unsigned long long
+insert_pclel (unsigned long long  insn,
+	      long long           value,
+	      const char **       errmsg)
+{
+  if (value != 63)
+    {
+      *errmsg = _("invalid register number, should be pcl");
+      return insn;
+    }
+
+  insn |= 0x0400;
+  return insn;
+}
+
+static long long
+extract_pclel (unsigned long long insn,
+	       bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (insn & 0x0400) ? 63 : -1;
+}
+
+#define INSERT_W6
+
+/* mask = 00000000000000000000111111000000
+   insn = 00011bbb000000000BBBwwwwwwDaaZZ1.  */
+
+static unsigned long long
+insert_w6 (unsigned long long  insn,
+	   long long           value,
+	   const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  insn |= ((value >> 0) & 0x003f) << 6;
+
+  return insn;
+}
+
+#define EXTRACT_W6
+
+/* mask = 00000000000000000000111111000000.  */
+
+static long long
+extract_w6 (unsigned long long insn,
+	    bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = 0;
+
+  value |= ((insn >> 6) & 0x003f) << 0;
+
+  /* Extend the sign.  */
+  int signbit = 1 << 5;
+  value = (value ^ signbit) - signbit;
+
+  return value;
+}
+
+#define INSERT_G_S
+
+/* mask = 0000011100022000
+   insn = 01000ggghhhGG0HH.  */
+
+static unsigned long long
+insert_g_s (unsigned long long  insn,
+	    long long           value,
+	    const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  insn |= ((value >> 0) & 0x0007) << 8;
+  insn |= ((value >> 3) & 0x0003) << 3;
+
+  return insn;
+}
+
+#define EXTRACT_G_S
+
+/* mask = 0000011100022000.  */
+
+static long long
+extract_g_s (unsigned long long insn,
+	     bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = 0;
+  int signbit = 1 << (6 - 1);
+
+  value |= ((insn >> 8) & 0x0007) << 0;
+  value |= ((insn >> 3) & 0x0003) << 3;
+
+  /* Extend the sign.  */
+  value = (value ^ signbit) - signbit;
+
+  return value;
+}
+
+/* ARC NPS400 Support: See comment near head of file.  */
+#define MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(NAME,OFFSET)          \
+static unsigned long long					 \
+insert_nps_3bit_reg_at_##OFFSET##_##NAME		         \
+                    (unsigned long long  insn,                   \
+                     long long           value,	                 \
+                     const char **       errmsg)	         \
+{								 \
+  switch (value)						 \
+    {								 \
+    case 0:                                                      \
+    case 1:                                                      \
+    case 2:                                                      \
+    case 3:                                                      \
+      insn |= value << (OFFSET);                                 \
+      break;                                                     \
+    case 12:                                                     \
+    case 13:                                                     \
+    case 14:                                                     \
+    case 15:                                                     \
+      insn |= (value - 8) << (OFFSET);                           \
+      break;                                                     \
+    default:                                                     \
+      *errmsg = _("register must be either r0-r3 or r12-r15");   \
+      break;                                                     \
+    }                                                            \
+  return insn;                                                   \
+}                                                                \
+                                                                 \
+static long long						 \
+extract_nps_3bit_reg_at_##OFFSET##_##NAME			 \
+  (unsigned long long insn,					 \
+   bool *invalid ATTRIBUTE_UNUSED)				 \
+{                                                                \
+  int value = (insn >> (OFFSET)) & 0x07;			 \
+  if (value > 3)                                                 \
+    value += 8;                                                  \
+  return value;                                                  \
+}                                                                \
+
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(dst,8)
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(dst,24)
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(dst,40)
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(dst,56)
+
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(src2,5)
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(src2,21)
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(src2,37)
+MAKE_3BIT_REG_INSERT_EXTRACT_FUNCS(src2,53)
+
+static unsigned long long
+insert_nps_bitop_size_2b (unsigned long long  insn,
+                          long long           value,
+                          const char **       errmsg)
+{
+  switch (value)
+    {
+    case 1:
+      value = 0;
+      break;
+    case 2:
+      value = 1;
+      break;
+    case 4:
+      value = 2;
+      break;
+    case 8:
+      value = 3;
+      break;
+    default:
+      value = 0;
+      *errmsg = _("invalid size, should be 1, 2, 4, or 8");
+      break;
+    }
+
+  insn |= value << 10;
+  return insn;
+}
+
+static long long
+extract_nps_bitop_size_2b (unsigned long long insn,
+                           bool *invalid ATTRIBUTE_UNUSED)
+{
+  return  1 << ((insn >> 10) & 0x3);
+}
+
+static unsigned long long
+insert_nps_bitop_uimm8 (unsigned long long  insn,
+                        long long           value,
+                        const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  insn |= ((value >> 5) & 7) << 12;
+  insn |= (value & 0x1f);
+  return insn;
+}
+
+static long long
+extract_nps_bitop_uimm8 (unsigned long long insn,
+                         bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (((insn >> 12) & 0x7) << 5) | (insn & 0x1f);
+}
+
+static unsigned long long
+insert_nps_rflt_uimm6 (unsigned long long  insn,
+                       long long           value,
+                       const char **       errmsg)
+{
+  switch (value)
+    {
+    case 1:
+    case 2:
+    case 4:
+      break;
+
+    default:
+      *errmsg = _("invalid immediate, must be 1, 2, or 4");
+      value = 0;
+    }
+
+  insn |= (value << 6);
+  return insn;
+}
+
+static long long
+extract_nps_rflt_uimm6 (unsigned long long insn,
+			bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (insn >> 6) & 0x3f;
+}
+
+static unsigned long long
+insert_nps_dst_pos_and_size (unsigned long long  insn,
+                             long long           value,
+                             const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  insn |= ((value & 0x1f) | (((32 - value - 1) & 0x1f) << 10));
+  return insn;
+}
+
+static long long
+extract_nps_dst_pos_and_size (unsigned long long insn,
+                              bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (insn & 0x1f);
+}
+
+static unsigned long long
+insert_nps_cmem_uimm16 (unsigned long long  insn,
+                        long long           value,
+                        const char **       errmsg)
+{
+  int top = (value >> 16) & 0xffff;
+
+  if (top != 0x0 && top != NPS_CMEM_HIGH_VALUE)
+    *errmsg = _("invalid value for CMEM ld/st immediate");
+  insn |= (value & 0xffff);
+  return insn;
+}
+
+static long long
+extract_nps_cmem_uimm16 (unsigned long long insn,
+                         bool *invalid ATTRIBUTE_UNUSED)
+{
+  return (NPS_CMEM_HIGH_VALUE << 16) | (insn & 0xffff);
+}
+
+static unsigned long long
+insert_nps_imm_offset (unsigned long long  insn,
+		       long long           value,
+		       const char **       errmsg)
+{
+  switch (value)
+    {
+    case 0:
+    case 16:
+    case 32:
+    case 48:
+    case 64:
+      value = value >> 4;
+      break;
+    default:
+      *errmsg = _("invalid position, should be 0, 16, 32, 48 or 64.");
+      value = 0;
+    }
+  insn |= (value << 10);
+  return insn;
+}
+
+static long long
+extract_nps_imm_offset (unsigned long long insn,
+			bool *invalid ATTRIBUTE_UNUSED)
+{
+  return ((insn >> 10) & 0x7) * 16;
+}
+
+static unsigned long long
+insert_nps_imm_entry (unsigned long long  insn,
+		      long long           value,
+		      const char **       errmsg)
+{
+  switch (value)
+    {
+    case 16:
+      value = 0;
+      break;
+    case 32:
+      value = 1;
+      break;
+    case 64:
+      value = 2;
+      break;
+    case 128:
+    value = 3;
+    break;
+    default:
+      *errmsg = _("invalid position, should be 16, 32, 64 or 128.");
+      value = 0;
+    }
+  insn |= (value << 2);
+  return insn;
+}
+
+static long long
+extract_nps_imm_entry (unsigned long long insn,
+		       bool *invalid ATTRIBUTE_UNUSED)
+{
+  int imm_entry = ((insn >> 2) & 0x7);
+  return (1 << (imm_entry + 4));
+}
+
+static unsigned long long
+insert_nps_size_16bit (unsigned long long  insn,
+		       long long           value,
+		       const char **       errmsg)
+{
+  if ((value < 1) || (value > 64))
+    {
+      *errmsg = _("invalid size value must be on range 1-64.");
+      value = 0;
+    }
+  value = value & 0x3f;
+  insn |= (value << 6);
+  return insn;
+}
+
+static long long
+extract_nps_size_16bit (unsigned long long insn,
+			bool *invalid ATTRIBUTE_UNUSED)
+{
+  return ((insn & 0xfc0) >> 6) ? ((insn & 0xfc0) >> 6) : 64;
+}
+
+
+#define MAKE_SRC_POS_INSERT_EXTRACT_FUNCS(NAME,SHIFT)	      \
+static unsigned long long				      \
+insert_nps_##NAME##_pos (unsigned long long  insn,	      \
+			 long long            value,	      \
+			 const char **        errmsg)	      \
+{                                                             \
+ switch (value)                                               \
+   {                                                          \
+   case 0:                                                    \
+   case 8:                                                    \
+   case 16:                                                   \
+   case 24:                                                   \
+     value = value / 8;                                       \
+     break;                                                   \
+   default:                                                   \
+     *errmsg = _("invalid position, should be 0, 8, 16, or 24");       \
+     value = 0;                                               \
+  }                                                           \
+  insn |= (value << SHIFT);                                   \
+  return insn;                                                \
+}                                                             \
+                                                              \
+static long long                                              \
+extract_nps_##NAME##_pos (unsigned long long insn,	      \
+                          bool *invalid ATTRIBUTE_UNUSED)     \
+{                                                             \
+  return ((insn >> SHIFT) & 0x3) * 8;                         \
+}
+
+MAKE_SRC_POS_INSERT_EXTRACT_FUNCS (src2, 12)
+MAKE_SRC_POS_INSERT_EXTRACT_FUNCS (src1, 10)
+
+#define MAKE_BIAS_INSERT_EXTRACT_FUNCS(NAME,LOWER,UPPER,BITS,BIAS,SHIFT) \
+static unsigned long long                                               \
+insert_nps_##NAME (unsigned long long  insn,				\
+		   long long           value,				\
+		   const char **       errmsg)				\
+  {                                                                     \
+    if (value < LOWER || value > UPPER)                                 \
+      {                                                                 \
+        *errmsg = _("invalid size, value must be "                      \
+                    #LOWER " to " #UPPER ".");                          \
+        return insn;                                                    \
+      }                                                                 \
+    value -= BIAS;                                                      \
+    insn |= (value << SHIFT);                                           \
+    return insn;                                                        \
+  }                                                                     \
+                                                                        \
+static long long                                                        \
+extract_nps_##NAME (unsigned long long insn,				\
+                    bool *invalid ATTRIBUTE_UNUSED)			\
+{                                                                       \
+  return ((insn >> SHIFT) & ((1 << BITS) - 1)) + BIAS;                  \
+}
+
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (addb_size,2,32,5,1,5)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (andb_size,1,32,5,1,5)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (fxorb_size,8,32,5,8,5)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (wxorb_size,16,32,5,16,5)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (bitop_size,1,32,5,1,10)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (qcmp_size,1,8,3,1,9)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (bitop1_size,1,32,5,1,20)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (bitop2_size,1,32,5,1,25)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (hash_width,1,32,5,1,6)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (hash_len,1,8,3,1,2)
+MAKE_BIAS_INSERT_EXTRACT_FUNCS (index3,4,7,2,4,0)
+
+static long long
+extract_nps_qcmp_m3 (unsigned long long insn,
+                     bool *invalid)
+{
+  int m3 = (insn >> 5) & 0xf;
+  if (m3 == 0xf)
+    *invalid = true;
+  return m3;
+}
+
+static long long
+extract_nps_qcmp_m2 (unsigned long long insn,
+                     bool *invalid)
+{
+  bool tmp_invalid = false;
+  int m2 = (insn >> 15) & 0x1;
+  int m3 = extract_nps_qcmp_m3 (insn, &tmp_invalid);
+
+  if (m2 == 0 && m3 == 0xf)
+    *invalid = true;
+  return m2;
+}
+
+static long long
+extract_nps_qcmp_m1 (unsigned long long insn,
+                     bool *invalid)
+{
+  bool tmp_invalid = false;
+  int m1 = (insn >> 14) & 0x1;
+  int m2 = extract_nps_qcmp_m2 (insn, &tmp_invalid);
+  int m3 = extract_nps_qcmp_m3 (insn, &tmp_invalid);
+
+  if (m1 == 0 && m2 == 0 && m3 == 0xf)
+    *invalid = true;
+  return m1;
+}
+
+static unsigned long long
+insert_nps_calc_entry_size (unsigned long long  insn,
+                            long long           value,
+                            const char **       errmsg)
+{
+  unsigned pwr;
+
+  if (value < 1 || value > 256)
+    {
+      *errmsg = _("value out of range 1 - 256");
+      return 0;
+    }
+
+  for (pwr = 0; (value & 1) == 0; value >>= 1)
+    ++pwr;
+
+  if (value != 1)
+    {
+      *errmsg = _("value must be power of 2");
+      return 0;
+    }
+
+  return insn | (pwr << 8);
+}
+
+static long long
+extract_nps_calc_entry_size (unsigned long long insn,
+                             bool *invalid ATTRIBUTE_UNUSED)
+{
+  unsigned entry_size = (insn >> 8) & 0xf;
+  return 1 << entry_size;
+}
+
+static unsigned long long
+insert_nps_bitop_mod4 (unsigned long long  insn,
+                           long long       value,
+                           const char **   errmsg ATTRIBUTE_UNUSED)
+{
+  return insn | ((value & 0x2) << 30) | ((value & 0x1) << 47);
+}
+
+static long long
+extract_nps_bitop_mod4 (unsigned long long insn,
+                            bool *invalid ATTRIBUTE_UNUSED)
+{
+  return ((insn >> 30) & 0x2) | ((insn >> 47) & 0x1);
+}
+
+static unsigned long long
+insert_nps_bitop_dst_pos3_pos4 (unsigned long long  insn,
+                                long long           value,
+                                const char **       errmsg ATTRIBUTE_UNUSED)
+{
+  return insn | (value << 42) | (value << 37);
+}
+
+static long long
+extract_nps_bitop_dst_pos3_pos4 (unsigned long long insn,
+                                 bool *invalid)
+{
+  if (((insn >> 42) & 0x1f) != ((insn >> 37) & 0x1f))
+    *invalid = true;
+  return ((insn >> 37) & 0x1f);
+}
+
+static unsigned long long
+insert_nps_bitop_ins_ext (unsigned long long  insn,
+                          long long           value,
+                          const char **       errmsg)
+{
+  if (value < 0 || value > 28)
+    *errmsg = _("value must be in the range 0 to 28");
+  return insn | (value << 20);
+}
+
+static long long
+extract_nps_bitop_ins_ext (unsigned long long insn,
+                           bool *invalid)
+{
+  int value = (insn >> 20) & 0x1f;
+
+  if (value > 28)
+    *invalid = true;
+  return value;
+}
+
+#define MAKE_1BASED_INSERT_EXTRACT_FUNCS(NAME,SHIFT,UPPER,BITS)         \
+static unsigned long long						\
+insert_nps_##NAME (unsigned long long  insn,				\
+		   long long           value,                           \
+		   const char **       errmsg)				\
+{                                                                       \
+  if (value < 1 || value > UPPER)                                       \
+    *errmsg = _("value must be in the range 1 to " #UPPER);             \
+  if (value == UPPER)                                                   \
+    value = 0;                                                          \
+  return insn | (value << SHIFT);                                       \
+}                                                                       \
+                                                                        \
+static long long							\
+extract_nps_##NAME (unsigned long long insn,				\
+                    bool *invalid ATTRIBUTE_UNUSED)			\
+{                                                                       \
+  int value = (insn >> SHIFT) & ((1 << BITS) - 1);                      \
+  if (value == 0)                                                       \
+    value = UPPER;                                                      \
+  return value;                                                         \
+}
+
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (field_size, 6, 8, 3)
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (shift_factor, 9, 8, 3)
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (bits_to_scramble, 12, 8, 3)
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (bdlen_max_len, 5, 256, 8)
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (bd_num_buff, 6, 8, 3)
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (pmu_num_job, 6, 4, 2)
+MAKE_1BASED_INSERT_EXTRACT_FUNCS (proto_size, 16, 64, 6)
+
+static unsigned long long
+insert_nps_min_hofs (unsigned long long  insn,
+                     long long           value,
+                     const char **       errmsg)
+{
+  if (value < 0 || value > 240)
+    *errmsg = _("value must be in the range 0 to 240");
+  if ((value % 16) != 0)
+    *errmsg = _("value must be a multiple of 16");
+  value = value / 16;
+  return insn | (value << 6);
+}
+
+static long long
+extract_nps_min_hofs (unsigned long long insn,
+                      bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = (insn >> 6) & 0xF;
+  return value * 16;
+}
+
+#define MAKE_INSERT_NPS_ADDRTYPE(NAME, VALUE)                          \
+static unsigned long long                                              \
+insert_nps_##NAME (unsigned long long  insn,			       \
+                   long long           value,			       \
+                   const char **       errmsg)			       \
+{                                                                      \
+  if (value != ARC_NPS400_ADDRTYPE_##VALUE)                            \
+    *errmsg = _("invalid address type for operand");                   \
+  return insn;                                                         \
+}                                                                      \
+                                                                       \
+static long long						       \
+extract_nps_##NAME (unsigned long long insn ATTRIBUTE_UNUSED,	       \
+		    bool *invalid ATTRIBUTE_UNUSED)		       \
+{                                                                      \
+  return ARC_NPS400_ADDRTYPE_##VALUE;                                  \
+}
+
+MAKE_INSERT_NPS_ADDRTYPE (bd, BD)
+MAKE_INSERT_NPS_ADDRTYPE (jid, JID)
+MAKE_INSERT_NPS_ADDRTYPE (lbd, LBD)
+MAKE_INSERT_NPS_ADDRTYPE (mbd, MBD)
+MAKE_INSERT_NPS_ADDRTYPE (sd, SD)
+MAKE_INSERT_NPS_ADDRTYPE (sm, SM)
+MAKE_INSERT_NPS_ADDRTYPE (xa, XA)
+MAKE_INSERT_NPS_ADDRTYPE (xd, XD)
+MAKE_INSERT_NPS_ADDRTYPE (cd, CD)
+MAKE_INSERT_NPS_ADDRTYPE (cbd, CBD)
+MAKE_INSERT_NPS_ADDRTYPE (cjid, CJID)
+MAKE_INSERT_NPS_ADDRTYPE (clbd, CLBD)
+MAKE_INSERT_NPS_ADDRTYPE (cm, CM)
+MAKE_INSERT_NPS_ADDRTYPE (csd, CSD)
+MAKE_INSERT_NPS_ADDRTYPE (cxa, CXA)
+MAKE_INSERT_NPS_ADDRTYPE (cxd, CXD)
+
+static unsigned long long
+insert_nps_rbdouble_64 (unsigned long long  insn,
+                        long long           value,
+                        const char **       errmsg)
+{
+  if (value < 0 || value > 31)
+    *errmsg = _("value must be in the range 0 to 31");
+  return insn | (value << 43) | (value << 48);
+}
+
+
+static long long
+extract_nps_rbdouble_64 (unsigned long long insn,
+                         bool *invalid)
+{
+  int value1 = (insn >> 43) & 0x1F;
+  int value2 = (insn >> 48) & 0x1F;
+
+  if (value1 != value2)
+    *invalid = true;
+
+  return value1;
+}
+
+static unsigned long long
+insert_nps_misc_imm_offset (unsigned long long  insn,
+			    long long           value,
+			    const char **       errmsg)
+{
+  if (value & 0x3)
+    {
+      *errmsg = _("invalid position, should be one of: 0,4,8,...124.");
+      value = 0;
+    }
+  insn |= (value << 6);
+  return insn;
+}
+
+static long long int
+extract_nps_misc_imm_offset (unsigned long long insn,
+			     bool *invalid ATTRIBUTE_UNUSED)
+{
+  return ((insn >> 8) & 0x1f) * 4;
+}
+
+static long long int
+extract_uimm12_20 (unsigned long long insn ATTRIBUTE_UNUSED,
+		   bool *invalid ATTRIBUTE_UNUSED)
+{
+  int value = 0;
+
+  value |= ((insn >> 6) & 0x003f) << 0;
+  value |= ((insn >> 0) & 0x003f) << 6;
+
+  return value;
+}
+
+/* Include the generic extract/insert functions.  Order is important
+   as some of the functions present in the .h may be disabled via
+   defines.  */
+#include "arc-fxi.h"
+
+/* The flag operands table.
+
+   The format of the table is
+   NAME CODE BITS SHIFT FAVAIL.  */
+const struct arc_flag_operand arc_flag_operands[] =
+{
+#define F_NULL	0
+  { 0, 0, 0, 0, 0},
+#define F_ALWAYS    (F_NULL + 1)
+  { "al", 0, 0, 0, 0 },
+#define F_RA	    (F_ALWAYS + 1)
+  { "ra", 0, 0, 0, 0 },
+#define F_EQUAL	    (F_RA + 1)
+  { "eq", 1, 5, 0, 1 },
+#define F_ZERO	    (F_EQUAL + 1)
+  { "z",  1, 5, 0, 0 },
+#define F_NOTEQUAL  (F_ZERO + 1)
+  { "ne", 2, 5, 0, 1 },
+#define F_NOTZERO   (F_NOTEQUAL + 1)
+  { "nz", 2, 5, 0, 0 },
+#define F_POZITIVE  (F_NOTZERO + 1)
+  { "p",  3, 5, 0, 1 },
+#define F_PL	    (F_POZITIVE + 1)
+  { "pl", 3, 5, 0, 0 },
+#define F_NEGATIVE  (F_PL + 1)
+  { "n",  4, 5, 0, 1 },
+#define F_MINUS	    (F_NEGATIVE + 1)
+  { "mi", 4, 5, 0, 0 },
+#define F_CARRY	    (F_MINUS + 1)
+  { "c",  5, 5, 0, 1 },
+#define F_CARRYSET  (F_CARRY + 1)
+  { "cs", 5, 5, 0, 0 },
+#define F_LOWER	    (F_CARRYSET + 1)
+  { "lo", 5, 5, 0, 0 },
+#define F_CARRYCLR  (F_LOWER + 1)
+  { "cc", 6, 5, 0, 0 },
+#define F_NOTCARRY (F_CARRYCLR + 1)
+  { "nc", 6, 5, 0, 1 },
+#define F_HIGHER   (F_NOTCARRY + 1)
+  { "hs", 6, 5, 0, 0 },
+#define F_OVERFLOWSET (F_HIGHER + 1)
+  { "vs", 7, 5, 0, 0 },
+#define F_OVERFLOW (F_OVERFLOWSET + 1)
+  { "v",  7, 5, 0, 1 },
+#define F_NOTOVERFLOW (F_OVERFLOW + 1)
+  { "nv", 8, 5, 0, 1 },
+#define F_OVERFLOWCLR (F_NOTOVERFLOW + 1)
+  { "vc", 8, 5, 0, 0 },
+#define F_GT	   (F_OVERFLOWCLR + 1)
+  { "gt", 9, 5, 0, 1 },
+#define F_GE	   (F_GT + 1)
+  { "ge", 10, 5, 0, 1 },
+#define F_LT	   (F_GE + 1)
+  { "lt", 11, 5, 0, 1 },
+#define F_LE	   (F_LT + 1)
+  { "le", 12, 5, 0, 1 },
+#define F_HI	   (F_LE + 1)
+  { "hi", 13, 5, 0, 1 },
+#define F_LS	   (F_HI + 1)
+  { "ls", 14, 5, 0, 1 },
+#define F_PNZ	   (F_LS + 1)
+  { "pnz", 15, 5, 0, 1 },
+#define F_NJ	   (F_PNZ + 1)
+  { "nj", 21, 5, 0, 1 },
+#define F_NM	   (F_NJ + 1)
+  { "nm", 23, 5, 0, 1 },
+#define F_NO_T	   (F_NM + 1)
+  { "nt", 24, 5, 0, 1 },
+
+  /* FLAG.  */
+#define F_FLAG     (F_NO_T + 1)
+  { "f",  1, 1, 15, 1 },
+#define F_FFAKE     (F_FLAG + 1)
+  { "f",  0, 0, 0, 1 },
+
+  /* Delay slot.  */
+#define F_ND	   (F_FFAKE + 1)
+  { "nd", 0, 1, 5, 0 },
+#define F_D	   (F_ND + 1)
+  { "d",  1, 1, 5, 1 },
+#define F_DFAKE	   (F_D + 1)
+  { "d",  0, 0, 0, 1 },
+#define F_DNZ_ND   (F_DFAKE + 1)
+  { "nd", 0, 1, 16, 0 },
+#define F_DNZ_D	   (F_DNZ_ND + 1)
+  { "d",  1, 1, 16, 1 },
+
+  /* Data size.  */
+#define F_SIZEB1   (F_DNZ_D + 1)
+  { "b", 1, 2, 1, 1 },
+#define F_SIZEB7   (F_SIZEB1 + 1)
+  { "b", 1, 2, 7, 1 },
+#define F_SIZEB17  (F_SIZEB7 + 1)
+  { "b", 1, 2, 17, 1 },
+#define F_SIZEW1   (F_SIZEB17 + 1)
+  { "w", 2, 2, 1, 0 },
+#define F_SIZEW7   (F_SIZEW1 + 1)
+  { "w", 2, 2, 7, 0 },
+#define F_SIZEW17  (F_SIZEW7 + 1)
+  { "w", 2, 2, 17, 0 },
+
+  /* Sign extension.  */
+#define F_SIGN6   (F_SIZEW17 + 1)
+  { "x", 1, 1, 6, 1 },
+#define F_SIGN16  (F_SIGN6 + 1)
+  { "x", 1, 1, 16, 1 },
+#define F_SIGNX   (F_SIGN16 + 1)
+  { "x", 0, 0, 0, 1 },
+
+  /* Address write-back modes.  */
+#define F_A3       (F_SIGNX + 1)
+  { "a", 1, 2, 3, 0 },
+#define F_A9       (F_A3 + 1)
+  { "a", 1, 2, 9, 0 },
+#define F_A22      (F_A9 + 1)
+  { "a", 1, 2, 22, 0 },
+#define F_AW3      (F_A22 + 1)
+  { "aw", 1, 2, 3, 1 },
+#define F_AW9      (F_AW3 + 1)
+  { "aw", 1, 2, 9, 1 },
+#define F_AW22     (F_AW9 + 1)
+  { "aw", 1, 2, 22, 1 },
+#define F_AB3      (F_AW22 + 1)
+  { "ab", 2, 2, 3, 1 },
+#define F_AB9      (F_AB3 + 1)
+  { "ab", 2, 2, 9, 1 },
+#define F_AB22     (F_AB9 + 1)
+  { "ab", 2, 2, 22, 1 },
+#define F_AS3      (F_AB22 + 1)
+  { "as", 3, 2, 3, 1 },
+#define F_AS9      (F_AS3 + 1)
+  { "as", 3, 2, 9, 1 },
+#define F_AS22     (F_AS9 + 1)
+  { "as", 3, 2, 22, 1 },
+#define F_ASFAKE   (F_AS22 + 1)
+  { "as", 0, 0, 0, 1 },
+
+  /* Cache bypass.  */
+#define F_DI5     (F_ASFAKE + 1)
+  { "di", 1, 1, 5, 1 },
+#define F_DI11    (F_DI5 + 1)
+  { "di", 1, 1, 11, 1 },
+#define F_DI14    (F_DI11 + 1)
+  { "di", 1, 1, 14, 1 },
+#define F_DI15    (F_DI14 + 1)
+  { "di", 1, 1, 15, 1 },
+
+  /* ARCv2 specific.  */
+#define F_NT     (F_DI15 + 1)
+  { "nt", 0, 1, 3, 1},
+#define F_T      (F_NT + 1)
+  { "t", 1, 1, 3, 1},
+#define F_H1     (F_T + 1)
+  { "h", 2, 2, 1, 1 },
+#define F_H7     (F_H1 + 1)
+  { "h", 2, 2, 7, 1 },
+#define F_H17    (F_H7 + 1)
+  { "h", 2, 2, 17, 1 },
+#define F_SIZED  (F_H17 + 1)
+  { "dd", 8, 0, 0, 0 },  /* Fake.  */
+
+  /* Fake Flags.  */
+#define F_NE   (F_SIZED + 1)
+  { "ne", 0, 0, 0, 1 },
+
+  /* ARC NPS400 Support: See comment near head of file.  */
+#define F_NPS_CL (F_NE + 1)
+  { "cl", 0, 0, 0, 1 },
+
+#define F_NPS_NA (F_NPS_CL + 1)
+  { "na", 1, 1, 9, 1 },
+
+#define F_NPS_SR (F_NPS_NA + 1)
+  { "s", 1, 1, 13, 1 },
+
+#define F_NPS_M (F_NPS_SR + 1)
+  { "m", 1, 1, 7, 1 },
+
+#define F_NPS_FLAG (F_NPS_M + 1)
+  { "f", 1, 1, 20, 1 },
+
+#define F_NPS_R     (F_NPS_FLAG + 1)
+  { "r",  1, 1, 15, 1 },
+
+#define F_NPS_RW     (F_NPS_R + 1)
+  { "rw", 0, 1, 7, 1 },
+
+#define F_NPS_RD     (F_NPS_RW + 1)
+  { "rd", 1, 1, 7, 1 },
+
+#define F_NPS_WFT     (F_NPS_RD + 1)
+  { "wft", 0, 0, 0, 1 },
+
+#define F_NPS_IE1     (F_NPS_WFT + 1)
+  { "ie1", 1, 2, 8, 1 },
+
+#define F_NPS_IE2     (F_NPS_IE1 + 1)
+  { "ie2", 2, 2, 8, 1 },
+
+#define F_NPS_IE12     (F_NPS_IE2 + 1)
+  { "ie12", 3, 2, 8, 1 },
+
+#define F_NPS_SYNC_RD     (F_NPS_IE12 + 1)
+  { "rd", 0, 1, 6, 1 },
+
+#define F_NPS_SYNC_WR     (F_NPS_SYNC_RD + 1)
+  { "wr", 1, 1, 6, 1 },
+
+#define F_NPS_HWS_OFF     (F_NPS_SYNC_WR + 1)
+  { "off", 0, 0, 0, 1 },
+
+#define F_NPS_HWS_RESTORE     (F_NPS_HWS_OFF + 1)
+  { "restore", 0, 0, 0, 1 },
+
+#define F_NPS_SX     (F_NPS_HWS_RESTORE + 1)
+  { "sx",  1, 1, 14, 1 },
+
+#define F_NPS_AR     (F_NPS_SX + 1)
+  { "ar",  0, 1, 0, 1 },
+
+#define F_NPS_AL     (F_NPS_AR + 1)
+  { "al",  1, 1, 0, 1 },
+
+#define F_NPS_S      (F_NPS_AL + 1)
+  { "s",   0, 0, 0, 1 },
+
+#define F_NPS_ZNCV_RD      (F_NPS_S + 1)
+  { "rd",  0, 1, 15, 1 },
+
+#define F_NPS_ZNCV_WR      (F_NPS_ZNCV_RD + 1)
+  { "wr",  1, 1, 15, 1 },
+
+#define F_NPS_P0      (F_NPS_ZNCV_WR + 1)
+  { "p0", 0, 0, 0, 1 },
+
+#define F_NPS_P1      (F_NPS_P0 + 1)
+  { "p1", 0, 0, 0, 1 },
+
+#define F_NPS_P2      (F_NPS_P1 + 1)
+  { "p2", 0, 0, 0, 1 },
+
+#define F_NPS_P3      (F_NPS_P2 + 1)
+  { "p3", 0, 0, 0, 1 },
+
+#define F_NPS_LDBIT_DI      (F_NPS_P3 + 1)
+  { "di", 0, 0, 0, 1 },
+
+#define F_NPS_LDBIT_CL1      (F_NPS_LDBIT_DI + 1)
+  { "cl", 1, 1, 6, 1 },
+
+#define F_NPS_LDBIT_CL2      (F_NPS_LDBIT_CL1 + 1)
+  { "cl", 1, 1, 16, 1 },
+
+#define F_NPS_LDBIT_X2_1      (F_NPS_LDBIT_CL2 + 1)
+  { "x2", 1, 2, 9, 1 },
+
+#define F_NPS_LDBIT_X2_2      (F_NPS_LDBIT_X2_1 + 1)
+  { "x2", 1, 2, 22, 1 },
+
+#define F_NPS_LDBIT_X4_1      (F_NPS_LDBIT_X2_2 + 1)
+  { "x4", 2, 2, 9, 1 },
+
+#define F_NPS_LDBIT_X4_2      (F_NPS_LDBIT_X4_1 + 1)
+  { "x4", 2, 2, 22, 1 },
+
+#define F_NPS_CORE     (F_NPS_LDBIT_X4_2 + 1)
+  { "core", 1, 3, 6, 1 },
+
+#define F_NPS_CLSR     (F_NPS_CORE + 1)
+  { "clsr", 2, 3, 6, 1 },
+
+#define F_NPS_ALL     (F_NPS_CLSR + 1)
+  { "all", 3, 3, 6, 1 },
+
+#define F_NPS_GIC     (F_NPS_ALL + 1)
+  { "gic", 4, 3, 6, 1 },
+
+#define F_NPS_RSPI_GIC     (F_NPS_GIC + 1)
+  { "gic", 5, 3, 6, 1 },
+};
+
+const unsigned arc_num_flag_operands = ARRAY_SIZE (arc_flag_operands);
+
+/* Table of the flag classes.
+
+   The format of the table is
+   CLASS {FLAG_CODE}.  */
+const struct arc_flag_class arc_flag_classes[] =
+{
+#define C_EMPTY     0
+  { F_CLASS_NONE, { F_NULL } },
+
+#define C_CC_EQ     (C_EMPTY + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_EQUAL, F_NULL} },
+
+#define C_CC_GE     (C_CC_EQ + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_GE, F_NULL} },
+
+#define C_CC_GT     (C_CC_GE + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_GT, F_NULL} },
+
+#define C_CC_HI     (C_CC_GT + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_HI, F_NULL} },
+
+#define C_CC_HS     (C_CC_HI + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_NOTCARRY, F_NULL} },
+
+#define C_CC_LE     (C_CC_HS + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_LE, F_NULL} },
+
+#define C_CC_LO     (C_CC_LE + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_CARRY, F_NULL} },
+
+#define C_CC_LS     (C_CC_LO + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_LS, F_NULL} },
+
+#define C_CC_LT     (C_CC_LS + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_LT, F_NULL} },
+
+#define C_CC_NE     (C_CC_LT + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_COND, {F_NOTEQUAL, F_NULL} },
+
+#define C_AA_AB     (C_CC_NE + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_WB, {F_AB3, F_NULL} },
+
+#define C_AA_AW     (C_AA_AB + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_WB, {F_AW3, F_NULL} },
+
+#define C_ZZ_D      (C_AA_AW + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_ZZ, {F_SIZED, F_NULL} },
+
+#define C_ZZ_H      (C_ZZ_D + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_ZZ, {F_H1, F_NULL} },
+
+#define C_ZZ_B      (C_ZZ_H + 1)
+  {F_CLASS_IMPLICIT | F_CLASS_ZZ, {F_SIZEB1, F_NULL} },
+
+#define C_CC	    (C_ZZ_B + 1)
+  { F_CLASS_OPTIONAL | F_CLASS_EXTEND | F_CLASS_COND,
+    { F_ALWAYS, F_RA, F_EQUAL, F_ZERO, F_NOTEQUAL,
+      F_NOTZERO, F_POZITIVE, F_PL, F_NEGATIVE, F_MINUS,
+      F_CARRY, F_CARRYSET, F_LOWER, F_CARRYCLR,
+      F_NOTCARRY, F_HIGHER, F_OVERFLOWSET, F_OVERFLOW,
+      F_NOTOVERFLOW, F_OVERFLOWCLR, F_GT, F_GE, F_LT,
+      F_LE, F_HI, F_LS, F_PNZ, F_NJ, F_NM, F_NO_T, F_NULL } },
+
+#define C_AA_ADDR3  (C_CC + 1)
+#define C_AA27	    (C_CC + 1)
+  { F_CLASS_OPTIONAL | F_CLASS_WB, { F_A3, F_AW3, F_AB3, F_AS3, F_NULL } },
+#define C_AA_ADDR9  (C_AA_ADDR3 + 1)
+#define C_AA21	     (C_AA_ADDR3 + 1)
+  { F_CLASS_OPTIONAL | F_CLASS_WB, { F_A9, F_AW9, F_AB9, F_AS9, F_NULL } },
+#define C_AA_ADDR22 (C_AA_ADDR9 + 1)
+#define C_AA8	   (C_AA_ADDR9 + 1)
+  { F_CLASS_OPTIONAL | F_CLASS_WB, { F_A22, F_AW22, F_AB22, F_AS22, F_NULL } },
+
+#define C_F	    (C_AA_ADDR22 + 1)
+  { F_CLASS_OPTIONAL, { F_FLAG, F_NULL } },
+#define C_FHARD	    (C_F + 1)
+  { F_CLASS_OPTIONAL, { F_FFAKE, F_NULL } },
+
+#define C_T	    (C_FHARD + 1)
+  { F_CLASS_OPTIONAL, { F_NT, F_T, F_NULL } },
+#define C_D	    (C_T + 1)
+  { F_CLASS_OPTIONAL, { F_ND, F_D, F_NULL } },
+#define C_DNZ_D     (C_D + 1)
+  { F_CLASS_OPTIONAL, { F_DNZ_ND, F_DNZ_D, F_NULL } },
+
+#define C_DHARD	    (C_DNZ_D + 1)
+  { F_CLASS_OPTIONAL, { F_DFAKE, F_NULL } },
+
+#define C_DI20	    (C_DHARD + 1)
+  { F_CLASS_OPTIONAL, { F_DI11, F_NULL }},
+#define C_DI14	    (C_DI20 + 1)
+  { F_CLASS_OPTIONAL, { F_DI14, F_NULL }},
+#define C_DI16	    (C_DI14 + 1)
+  { F_CLASS_OPTIONAL, { F_DI15, F_NULL }},
+#define C_DI26	    (C_DI16 + 1)
+  { F_CLASS_OPTIONAL, { F_DI5, F_NULL }},
+
+#define C_X25	    (C_DI26 + 1)
+  { F_CLASS_OPTIONAL, { F_SIGN6, F_NULL }},
+#define C_X15	   (C_X25 + 1)
+  { F_CLASS_OPTIONAL, { F_SIGN16, F_NULL }},
+#define C_XHARD	   (C_X15 + 1)
+#define C_X	   (C_X15 + 1)
+  { F_CLASS_OPTIONAL, { F_SIGNX, F_NULL }},
+
+#define C_ZZ13	      (C_X + 1)
+  { F_CLASS_OPTIONAL, { F_SIZEB17, F_SIZEW17, F_H17, F_NULL}},
+#define C_ZZ23	      (C_ZZ13 + 1)
+  { F_CLASS_OPTIONAL, { F_SIZEB7, F_SIZEW7, F_H7, F_NULL}},
+#define C_ZZ29	      (C_ZZ23 + 1)
+  { F_CLASS_OPTIONAL, { F_SIZEB1, F_SIZEW1, F_H1, F_NULL}},
+
+#define C_AS	    (C_ZZ29 + 1)
+  { F_CLASS_OPTIONAL, { F_ASFAKE, F_NULL}},
+
+#define C_NE	    (C_AS + 1)
+  { F_CLASS_REQUIRED, { F_NE, F_NULL}},
+
+  /* ARC NPS400 Support: See comment near head of file.  */
+#define C_NPS_CL     (C_NE + 1)
+  { F_CLASS_REQUIRED, { F_NPS_CL, F_NULL}},
+
+#define C_NPS_NA     (C_NPS_CL + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_NA, F_NULL}},
+
+#define C_NPS_SR     (C_NPS_NA + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_SR, F_NULL}},
+
+#define C_NPS_M     (C_NPS_SR + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_M, F_NULL}},
+
+#define C_NPS_F     (C_NPS_M + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_FLAG, F_NULL}},
+
+#define C_NPS_R     (C_NPS_F + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_R, F_NULL}},
+
+#define C_NPS_SCHD_RW     (C_NPS_R + 1)
+  { F_CLASS_REQUIRED, { F_NPS_RW, F_NPS_RD, F_NULL}},
+
+#define C_NPS_SCHD_TRIG     (C_NPS_SCHD_RW + 1)
+  { F_CLASS_REQUIRED, { F_NPS_WFT, F_NULL}},
+
+#define C_NPS_SCHD_IE     (C_NPS_SCHD_TRIG + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_IE1, F_NPS_IE2, F_NPS_IE12, F_NULL}},
+
+#define C_NPS_SYNC     (C_NPS_SCHD_IE + 1)
+  { F_CLASS_REQUIRED, { F_NPS_SYNC_RD, F_NPS_SYNC_WR, F_NULL}},
+
+#define C_NPS_HWS_OFF     (C_NPS_SYNC + 1)
+  { F_CLASS_REQUIRED, { F_NPS_HWS_OFF, F_NULL}},
+
+#define C_NPS_HWS_RESTORE     (C_NPS_HWS_OFF + 1)
+  { F_CLASS_REQUIRED, { F_NPS_HWS_RESTORE, F_NULL}},
+
+#define C_NPS_SX     (C_NPS_HWS_RESTORE + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_SX, F_NULL}},
+
+#define C_NPS_AR_AL     (C_NPS_SX + 1)
+  { F_CLASS_REQUIRED, { F_NPS_AR, F_NPS_AL, F_NULL}},
+
+#define C_NPS_S    (C_NPS_AR_AL + 1)
+  { F_CLASS_REQUIRED, { F_NPS_S, F_NULL}},
+
+#define C_NPS_ZNCV    (C_NPS_S + 1)
+  { F_CLASS_REQUIRED, { F_NPS_ZNCV_RD, F_NPS_ZNCV_WR, F_NULL}},
+
+#define C_NPS_P0    (C_NPS_ZNCV + 1)
+  { F_CLASS_REQUIRED, { F_NPS_P0, F_NULL }},
+
+#define C_NPS_P1    (C_NPS_P0 + 1)
+  { F_CLASS_REQUIRED, { F_NPS_P1, F_NULL }},
+
+#define C_NPS_P2    (C_NPS_P1 + 1)
+  { F_CLASS_REQUIRED, { F_NPS_P2, F_NULL }},
+
+#define C_NPS_P3    (C_NPS_P2 + 1)
+  { F_CLASS_REQUIRED, { F_NPS_P3, F_NULL }},
+
+#define C_NPS_LDBIT_DI    (C_NPS_P3 + 1)
+  { F_CLASS_REQUIRED, { F_NPS_LDBIT_DI, F_NULL }},
+
+#define C_NPS_LDBIT_CL1    (C_NPS_LDBIT_DI + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_LDBIT_CL1, F_NULL }},
+
+#define C_NPS_LDBIT_CL2    (C_NPS_LDBIT_CL1 + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_LDBIT_CL2, F_NULL }},
+
+#define C_NPS_LDBIT_X_1    (C_NPS_LDBIT_CL2 + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_LDBIT_X2_1, F_NPS_LDBIT_X4_1, F_NULL }},
+
+#define C_NPS_LDBIT_X_2    (C_NPS_LDBIT_X_1 + 1)
+  { F_CLASS_OPTIONAL, { F_NPS_LDBIT_X2_2, F_NPS_LDBIT_X4_2, F_NULL }},
+
+#define C_NPS_CORE     (C_NPS_LDBIT_X_2 + 1)
+  { F_CLASS_REQUIRED, { F_NPS_CORE, F_NULL}},
+
+#define C_NPS_CLSR     (C_NPS_CORE + 1)
+  { F_CLASS_REQUIRED, { F_NPS_CLSR, F_NULL}},
+
+#define C_NPS_ALL     (C_NPS_CLSR + 1)
+  { F_CLASS_REQUIRED, { F_NPS_ALL, F_NULL}},
+
+#define C_NPS_GIC     (C_NPS_ALL + 1)
+  { F_CLASS_REQUIRED, { F_NPS_GIC, F_NULL}},
+
+#define C_NPS_RSPI_GIC     (C_NPS_GIC + 1)
+  { F_CLASS_REQUIRED, { F_NPS_RSPI_GIC, F_NULL}},
+};
+
+const unsigned char flags_none[] = { 0 };
+const unsigned char flags_f[]    = { C_F };
+const unsigned char flags_cc[]   = { C_CC };
+const unsigned char flags_ccf[]  = { C_CC, C_F };
+
+/* The operands table.
+
+   The format of the operands table is:
+
+   BITS SHIFT DEFAULT_RELOC FLAGS INSERT_FUN EXTRACT_FUN.  */
+const struct arc_operand arc_operands[] =
+{
+  /* The fields are bits, shift, insert, extract, flags.  The zero
+     index is used to indicate end-of-list.  */
+#define UNUSED		0
+  { 0, 0, 0, 0, 0, 0 },
+
+#define IGNORED		(UNUSED + 1)
+  { 0, 0, 0, ARC_OPERAND_IGNORE | ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, 0, 0 },
+
+  /* The plain integer register fields.  Used by 32 bit
+     instructions.  */
+#define RA		(IGNORED + 1)
+  { 6, 0, 0, ARC_OPERAND_IR, 0, 0 },
+#define RA_CHK		(RA + 1)
+  { 6, 0, 0, ARC_OPERAND_IR, insert_ra_chk, 0 },
+#define RB		(RA_CHK + 1)
+  { 6, 12, 0, ARC_OPERAND_IR, insert_rb, extract_rb },
+#define RB_CHK		(RB + 1)
+  { 6, 12, 0, ARC_OPERAND_IR, insert_rb_chk, extract_rb },
+#define RC		(RB_CHK + 1)
+  { 6, 6, 0, ARC_OPERAND_IR, 0, 0 },
+#define RBdup		(RC + 1)
+  { 6, 12, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE, insert_rb, extract_rb },
+
+#define RAD		(RBdup + 1)
+  { 6, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_TRUNCATE, insert_rad, 0 },
+#define RAD_CHK		(RAD + 1)
+  { 6, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_TRUNCATE, insert_rad, 0 },
+#define RCD		(RAD_CHK + 1)
+  { 6, 6, 0, ARC_OPERAND_IR | ARC_OPERAND_TRUNCATE, insert_rcd, 0 },
+#define RBD		(RCD + 1)
+  { 6, 6, 0, ARC_OPERAND_IR | ARC_OPERAND_TRUNCATE, insert_rbd, extract_rb },
+#define RBDdup		(RBD + 1)
+  { 6, 12, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE | ARC_OPERAND_TRUNCATE,
+    insert_rbd, extract_rb },
+
+  /* The plain integer register fields.  Used by short
+     instructions.  */
+#define RA16		(RBDdup + 1)
+#define RA_S		(RBDdup + 1)
+  { 4, 0, 0, ARC_OPERAND_IR, insert_ras, extract_ras },
+#define RB16		(RA16 + 1)
+#define RB_S		(RA16 + 1)
+  { 4, 8, 0, ARC_OPERAND_IR, insert_rbs, extract_rbs },
+#define RB16dup		(RB16 + 1)
+#define RB_Sdup		(RB16 + 1)
+  { 4, 8, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE, insert_rbs, extract_rbs },
+#define RC16		(RB16dup + 1)
+#define RC_S		(RB16dup + 1)
+  { 4, 5, 0, ARC_OPERAND_IR, insert_rcs, extract_rcs },
+#define R6H		(RC16 + 1)   /* 6bit register field 'h' used
+					by V1 cpus.  */
+  { 6, 5, 0, ARC_OPERAND_IR, insert_rhv1, extract_rhv1 },
+#define R5H		(R6H + 1)    /* 5bit register field 'h' used
+					by V2 cpus.  */
+#define RH_S		(R6H + 1)    /* 5bit register field 'h' used
+					by V2 cpus.  */
+  { 5, 5, 0, ARC_OPERAND_IR, insert_rhv2, extract_rhv2 },
+#define R5Hdup		(R5H + 1)
+#define RH_Sdup		(R5H + 1)
+  { 5, 5, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE,
+    insert_rhv2, extract_rhv2 },
+
+#define RG		(R5Hdup + 1)
+#define G_S		(R5Hdup + 1)
+  { 5, 5, 0, ARC_OPERAND_IR, insert_g_s, extract_g_s },
+
+  /* Fix registers.  */
+#define R0		(RG + 1)
+#define R0_S		(RG + 1)
+  { 0, 0, 0, ARC_OPERAND_IR, insert_r0, extract_r0 },
+#define R1		(R0 + 1)
+#define R1_S		(R0 + 1)
+  { 1, 0, 0, ARC_OPERAND_IR, insert_r1, extract_r1 },
+#define R2		(R1 + 1)
+#define R2_S		(R1 + 1)
+  { 2, 0, 0, ARC_OPERAND_IR, insert_r2, extract_r2 },
+#define R3		(R2 + 1)
+#define R3_S		(R2 + 1)
+  { 2, 0, 0, ARC_OPERAND_IR, insert_r3, extract_r3 },
+#define RSP		(R3 + 1)
+#define SP_S		(R3 + 1)
+  { 5, 0, 0, ARC_OPERAND_IR, insert_sp, extract_sp },
+#define SPdup		(RSP + 1)
+#define SP_Sdup		(RSP + 1)
+  { 5, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE, insert_sp, extract_sp },
+#define GP		(SPdup + 1)
+#define GP_S		(SPdup + 1)
+  { 5, 0, 0, ARC_OPERAND_IR, insert_gp, extract_gp },
+
+#define PCL_S		(GP + 1)
+  { 1, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_NCHK, insert_pcl, extract_pcl },
+
+#define BLINK		(PCL_S + 1)
+#define BLINK_S		(PCL_S + 1)
+  { 5, 0, 0, ARC_OPERAND_IR, insert_blink, extract_blink },
+
+#define ILINK1		(BLINK + 1)
+  { 5, 0, 0, ARC_OPERAND_IR, insert_ilink1, extract_ilink1 },
+#define ILINK2		(ILINK1 + 1)
+  { 5, 0, 0, ARC_OPERAND_IR, insert_ilink2, extract_ilink2 },
+
+  /* Long immediate.  */
+#define LIMM		(ILINK2 + 1)
+#define LIMM_S		(ILINK2 + 1)
+  { 32, 0, BFD_RELOC_ARC_32_ME, ARC_OPERAND_LIMM, insert_limm, 0 },
+#define LIMMdup		(LIMM + 1)
+  { 32, 0, 0, ARC_OPERAND_LIMM | ARC_OPERAND_DUPLICATE, insert_limm, 0 },
+
+  /* Special operands.  */
+#define ZA		(LIMMdup + 1)
+#define ZB		(LIMMdup + 1)
+#define ZA_S		(LIMMdup + 1)
+#define ZB_S		(LIMMdup + 1)
+#define ZC_S		(LIMMdup + 1)
+  { 0, 0, 0, ARC_OPERAND_UNSIGNED, insert_za, 0 },
+
+#define RRANGE_EL	(ZA + 1)
+  { 4, 0, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK | ARC_OPERAND_TRUNCATE,
+    insert_rrange, extract_rrange},
+#define R13_EL		(RRANGE_EL + 1)
+  { 1, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_IGNORE | ARC_OPERAND_NCHK,
+    insert_r13el, extract_rrange },
+#define FP_EL		(R13_EL + 1)
+  { 1, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_IGNORE | ARC_OPERAND_NCHK,
+    insert_fpel, extract_fpel },
+#define BLINK_EL	(FP_EL + 1)
+  { 1, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_IGNORE | ARC_OPERAND_NCHK,
+    insert_blinkel, extract_blinkel },
+#define PCL_EL		(BLINK_EL + 1)
+  { 1, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_IGNORE | ARC_OPERAND_NCHK,
+    insert_pclel, extract_pclel },
+
+  /* Fake operand to handle the T flag.  */
+#define BRAKET		(PCL_EL + 1)
+#define BRAKETdup	(PCL_EL + 1)
+  { 0, 0, 0, ARC_OPERAND_FAKE | ARC_OPERAND_BRAKET, 0, 0 },
+
+  /* Fake operand to handle the T flag.  */
+#define FKT_T		(BRAKET + 1)
+  { 1, 3, 0, ARC_OPERAND_FAKE, insert_Ybit, 0 },
+  /* Fake operand to handle the T flag.  */
+#define FKT_NT		(FKT_T + 1)
+  { 1, 3, 0, ARC_OPERAND_FAKE, insert_NYbit, 0 },
+
+  /* UIMM6_20 mask = 00000000000000000000111111000000.  */
+#define UIMM6_20       (FKT_NT + 1)
+  {6, 0, 0, ARC_OPERAND_UNSIGNED, insert_uimm6_20, extract_uimm6_20},
+
+  /* Exactly like the above but used by relaxation.  */
+#define UIMM6_20R      (UIMM6_20 + 1)
+  {6, 0, -UIMM6_20R, ARC_OPERAND_UNSIGNED | ARC_OPERAND_PCREL,
+   insert_uimm6_20, extract_uimm6_20},
+
+  /* SIMM12_20 mask = 00000000000000000000111111222222.  */
+#define SIMM12_20	(UIMM6_20R + 1)
+  {12, 0, 0, ARC_OPERAND_SIGNED, insert_simm12_20, extract_simm12_20},
+
+  /* Exactly like the above but used by relaxation.  */
+#define SIMM12_20R	(SIMM12_20 + 1)
+  {12, 0, -SIMM12_20R, ARC_OPERAND_SIGNED | ARC_OPERAND_PCREL,
+   insert_simm12_20, extract_simm12_20},
+
+  /* UIMM12_20 mask = 00000000000000000000111111222222.  */
+#define UIMM12_20	(SIMM12_20R + 1)
+  {12, 0, 0, ARC_OPERAND_UNSIGNED, insert_simm12_20, extract_uimm12_20},
+
+  /* SIMM3_5_S mask = 0000011100000000.  */
+#define SIMM3_5_S	(UIMM12_20 + 1)
+  {3, 0, 0, ARC_OPERAND_SIGNED | ARC_OPERAND_NCHK,
+   insert_simm3s, extract_simm3s},
+
+  /* UIMM7_A32_11_S mask = 0000000000011111.  */
+#define UIMM7_A32_11_S	     (SIMM3_5_S + 1)
+  {7, 0, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_ALIGNED32
+   | ARC_OPERAND_TRUNCATE | ARC_OPERAND_IGNORE, insert_uimm7_a32_11_s,
+   extract_uimm7_a32_11_s},
+
+  /* The same as above but used by relaxation.  */
+#define UIMM7_A32_11R_S	     (UIMM7_A32_11_S + 1)
+  {7, 0, -UIMM7_A32_11R_S, ARC_OPERAND_UNSIGNED | ARC_OPERAND_ALIGNED32
+   | ARC_OPERAND_TRUNCATE | ARC_OPERA[...]

[diff truncated at 100000 bytes]

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-09-25 14:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-25 14:08 [binutils-gdb] Revert "arc: Add new opcode functions for ARCv3 ISA." Claudiu Zissulescu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).