This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/4] Add support for .extInstruction pseudo-op.


The arc assembler allows an user to define his/her own conditional
codes, custom instructions, auxiliary and core registers. This patch
re-adds support for the custom instructions.

OK to apply?
Claudiu

gas/
2016-04-04  Claudiu Zissulescu  <claziss@synopsys.com>

	* testsuite/gas/arc/textinsn-errors.d: New File.
	* testsuite/gas/arc/textinsn-errors.err: Likewise.
	* testsuite/gas/arc/textinsn-errors.s: Likewise.
	* testsuite/gas/arc/textinsn2op.d: Likewise.
	* testsuite/gas/arc/textinsn2op.s: Likewise.
	* testsuite/gas/arc/textinsn2op01.d: Likewise.
	* testsuite/gas/arc/textinsn2op01.s: Likewise.
	* testsuite/gas/arc/textinsn3op.d: Likewise.
	* testsuite/gas/arc/textinsn3op.s: Likewise.
	* doc/c-arc.texi (ARC Directives): Add .extInstruction
	documentation.
	* config/tc-arc.c (arcext_section): New variable.
	(arc_extinsn): New function.
	(md_pseudo_table): Add .extInstruction pseudo op.
	(attributes_t): New type.
	(suffixclass, syntaxclass, syntaxclassmod): New constant
	structures.
	(find_opcode_match): Remove arc_num_opcodes.
	(md_begin): Likewise.
	(tokenize_extinsn): New function.
	(arc_set_ext_seg): Likewise.
	(create_extinst_section): Likewise.

include/
2016-04-04  Claudiu Zissulescu  <claziss@synopsys.com>

	* opcode/arc.h (arc_num_opcodes): Remove.
	(ARC_SYNTAX_3OP, ARC_SYNTAX_2OP, ARC_OP1_MUST_BE_IMM)
	(ARC_OP1_IMM_IMPLIED, ARC_SUFFIX_NONE, ARC_SUFFIX_COND)
	(ARC_SUFFIX_FLAG): Define.
	(flags_none, flags_f, flags_cc, flags_ccf): Declare.
	(arg_none, arg_32bit_rarbrc, arg_32bit_zarbrc, arg_32bit_rbrbrc)
	(arg_32bit_rarbu6, arg_32bit_zarbu6, arg_32bit_rbrbu6)
	(arg_32bit_rbrbs12, arg_32bit_ralimmrc, arg_32bit_rarblimm)
	(arg_32bit_zalimmrc, arg_32bit_zarblimm, arg_32bit_rbrblimm)
	(arg_32bit_ralimmu6, arg_32bit_zalimmu6, arg_32bit_zalimms12)
	(arg_32bit_ralimmlimm, arg_32bit_zalimmlimm, arg_32bit_rbrc)
	(arg_32bit_zarc, arg_32bit_rbu6, arg_32bit_zau6, arg_32bit_rblimm)
	(arg_32bit_zalimm, arg_32bit_limmrc, arg_32bit_limmu6)
	(arg_32bit_limms12, arg_32bit_limmlimm): Likewise.

opcodes/
2016-04-04  Claudiu Zissulescu  <claziss@synopsys.com>

	* arc-opc.c (flags_none, flags_f, flags_cc, flags_ccf):
	Initialize.
	(arg_none, arg_32bit_rarbrc, arg_32bit_zarbrc, arg_32bit_rbrbrc)
	(arg_32bit_rarbu6, arg_32bit_zarbu6, arg_32bit_rbrbu6)
	(arg_32bit_rbrbs12, arg_32bit_ralimmrc, arg_32bit_rarblimm)
	(arg_32bit_zalimmrc, arg_32bit_zarblimm, arg_32bit_rbrblimm)
	(arg_32bit_ralimmu6, arg_32bit_zalimmu6, arg_32bit_zalimms12)
	(arg_32bit_ralimmlimm, arg_32bit_zalimmlimm, arg_32bit_rbrc)
	(arg_32bit_zarc, arg_32bit_rbu6, arg_32bit_zau6, arg_32bit_rblimm)
	(arg_32bit_zalimm, arg_32bit_limmrc, arg_32bit_limmu6)
	(arg_32bit_limms12, arg_32bit_limmlimm): Likewise.
	(arc_opcode arc_opcodes): Null terminate the array.
	(arc_num_opcodes): Remove.
	* arc-ext.h (INSERT_XOP): Define.
	(extInstruction_t): Likewise.
	(arcExtMap_instName): Delete.
	(arcExtMap_insn): New function.
	(arcExtMap_genOpcode): Likewise.
	* arc-ext.c (ExtInstruction): Remove.
	(create_map): Zero initialize instruction fields.
	(arcExtMap_instName): Remove.
	(arcExtMap_insn): New function.
	(dump_ARC_extmap): More info while debuging.
	(arcExtMap_genOpcode): New function.
	* arc-dis.c (find_format): New function.
	(print_insn_arc): Use find_format.
	(arc_get_disassembler): Enable dump_ARC_extmap only when
	debugging.

Signed-off-by: Claudiu Zissulescu <claziss@synopsys.com>
---
 gas/config/tc-arc.c                       | 383 +++++++++++++++++++++++++++---
 gas/doc/c-arc.texi                        |  95 +++++++-
 gas/testsuite/gas/arc/textinsn-errors.d   |   1 +
 gas/testsuite/gas/arc/textinsn-errors.err |   2 +
 gas/testsuite/gas/arc/textinsn-errors.s   |   1 +
 gas/testsuite/gas/arc/textinsn2op.d       |  24 ++
 gas/testsuite/gas/arc/textinsn2op.s       |  22 ++
 gas/testsuite/gas/arc/textinsn2op01.d     |  27 +++
 gas/testsuite/gas/arc/textinsn2op01.s     |  26 ++
 gas/testsuite/gas/arc/textinsn3op.d       |  63 +++++
 gas/testsuite/gas/arc/textinsn3op.s       |  64 +++++
 include/opcode/arc.h                      |  51 +++-
 opcodes/arc-dis.c                         | 228 ++++++++++--------
 opcodes/arc-ext.c                         | 306 ++++++++++++++++++++++--
 opcodes/arc-ext.h                         |  51 +++-
 opcodes/arc-opc.c                         |  42 +++-
 16 files changed, 1226 insertions(+), 160 deletions(-)
 create mode 100644 gas/testsuite/gas/arc/textinsn-errors.d
 create mode 100644 gas/testsuite/gas/arc/textinsn-errors.err
 create mode 100644 gas/testsuite/gas/arc/textinsn-errors.s
 create mode 100644 gas/testsuite/gas/arc/textinsn2op.d
 create mode 100644 gas/testsuite/gas/arc/textinsn2op.s
 create mode 100644 gas/testsuite/gas/arc/textinsn2op01.d
 create mode 100644 gas/testsuite/gas/arc/textinsn2op01.s
 create mode 100644 gas/testsuite/gas/arc/textinsn3op.d
 create mode 100644 gas/testsuite/gas/arc/textinsn3op.s

diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index 98cac6a..3dc3449 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -29,6 +29,7 @@
 
 #include "opcode/arc.h"
 #include "elf/arc.h"
+#include "../opcodes/arc-ext.h"
 
 /* Defines section.  */
 
@@ -126,6 +127,9 @@ extern int target_big_endian;
 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
 static int byte_order = DEFAULT_BYTE_ORDER;
 
+/* Arc extension section.  */
+static segT arcext_section;
+
 /* By default relaxation is disabled.  */
 static int relaxation_state = 0;
 
@@ -135,7 +139,7 @@ extern int arc_get_mach (char *);
 static void arc_lcomm (int);
 static void arc_option (int);
 static void arc_extra_reloc (int);
-
+static void arc_extinsn (int);
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -147,6 +151,8 @@ const pseudo_typeS md_pseudo_table[] =
   { "lcommon", arc_lcomm, 0 },
   { "cpu",     arc_option, 0 },
 
+  { "extinstruction", arc_extinsn, 0 },
+
   { "tls_gd_ld",   arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
   { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
 
@@ -308,6 +314,35 @@ static struct arc_last_insn
   bfd_boolean has_delay_slot;
 } arc_last_insns[2];
 
+/* Extension instruction suffix classes.  */
+typedef struct
+{
+  const char *name;
+  int  len;
+  int  class;
+} attributes_t;
+
+static const attributes_t suffixclass[] =
+{
+  { "SUFFIX_FLAG", 11, ARC_SUFFIX_FLAG },
+  { "SUFFIX_COND", 11, ARC_SUFFIX_COND },
+  { "SUFFIX_NONE", 11, ARC_SUFFIX_NONE }
+};
+
+/* Extension instruction syntax classes.  */
+static const attributes_t syntaxclass[] =
+{
+  { "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
+  { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP }
+};
+
+/* Extension instruction syntax classes modifiers.  */
+static const attributes_t syntaxclassmod[] =
+{
+  { "OP1_IMM_IMPLIED" , 15, ARC_OP1_IMM_IMPLIED },
+  { "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
+};
+
 /* Structure to hold an entry in ARC_OPCODE_HASH.  */
 struct arc_opcode_hash_entry
 {
@@ -615,8 +650,8 @@ arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
       const char *old_name = iter->opcode->name;
 
       iter->opcode++;
-      if ((iter->opcode - arc_opcodes >= (int) arc_num_opcodes)
-	  || (strcmp (old_name, iter->opcode->name) != 0))
+      if (iter->opcode->name
+	  && (strcmp (old_name, iter->opcode->name) != 0))
 	{
 	  iter->index++;
 	  if (iter->index == entry->count)
@@ -629,6 +664,40 @@ arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
   return iter->opcode;
 }
 
+/* Insert an opcode into opcode hash structure.  */
+
+static void
+arc_insert_opcode (const struct arc_opcode *opcode)
+{
+  const char *name, *retval;
+  struct arc_opcode_hash_entry *entry;
+  name = opcode->name;
+
+  entry = hash_find (arc_opcode_hash, name);
+  if (entry == NULL)
+    {
+      entry = xmalloc (sizeof (*entry));
+      entry->count = 0;
+      entry->opcode = NULL;
+
+      retval = hash_insert (arc_opcode_hash, name, (void *) entry);
+      if (retval)
+	as_fatal (_("internal error: can't hash opcode '%s': %s"),
+		  name, retval);
+    }
+
+  entry->opcode = xrealloc (entry->opcode,
+			    sizeof (const struct arc_opcode *)
+			    * (entry->count + 1));
+
+  if (entry->opcode == NULL)
+    as_fatal (_("Virtual memory exhausted"));
+
+  entry->opcode[entry->count] = opcode;
+  entry->count++;
+}
+
+
 /* Like md_number_to_chars but used for limms.  The 4-byte limm value,
    is encoded as 'middle-endian' for a little-endian target.  FIXME!
    this function is used for regular 4 byte instructions as well.  */
@@ -1611,7 +1680,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
 			     from BKTOK.  */
 			  tok[tokidx].X_op = O_constant;
 			  tok[tokidx].X_add_number = auxr->address;
-			  ARC_SET_FLAG (tok[i].X_add_symbol, ARC_FLAG_AUX);
+			  ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
 			  break;
 			}
 
@@ -2218,7 +2287,7 @@ declare_register_set (void)
 void
 md_begin (void)
 {
-  unsigned int i;
+  const struct arc_opcode *opcode = arc_opcodes;
 
   if (!mach_type_specified_p)
     arc_select_cpu ("arc700");
@@ -2238,37 +2307,17 @@ md_begin (void)
     as_fatal (_("Virtual memory exhausted"));
 
   /* Initialize the hash table with the insns.  */
-  for (i = 0; i < arc_num_opcodes;)
+  do
     {
-      const char *name, *retval;
-      struct arc_opcode_hash_entry *entry;
-
-      name = arc_opcodes[i].name;
-
-      entry = hash_find (arc_opcode_hash, name);
-      if (entry == NULL)
-        {
-          entry = xmalloc (sizeof (*entry));
-          entry->count = 0;
-          entry->opcode = NULL;
-
-          retval = hash_insert (arc_opcode_hash, name, (void *) entry);
-          if (retval)
-            as_fatal (_("internal error: can't hash opcode '%s': %s"),
-                      name, retval);
-        }
+      const char *name = opcode->name;
 
-      entry->opcode = xrealloc (entry->opcode,
-                                sizeof (const struct arc_opcode *)
-                                * entry->count + 1);
-      entry->opcode [entry->count] = &arc_opcodes[i];
-      entry->count++;
+      arc_insert_opcode (opcode);
 
-      while (++i < arc_num_opcodes
-	     && (arc_opcodes[i].name == name
-		 || !strcmp (arc_opcodes[i].name, name)))
+      while (++opcode && opcode->name
+	     && (opcode->name == name
+		 || !strcmp (opcode->name, name)))
 	continue;
-    }
+    }while (opcode->name);
 
   /* Register declaration.  */
   arc_reg_hash = hash_new ();
@@ -3877,3 +3926,273 @@ arc_adjust_symtab (void)
   /* Now do generic ELF adjustments.  */
   elf_adjust_symtab ();
 }
+
+static void tokenize_extinsn (extInstruction_t *einsn)
+{
+  char *p, c;
+  char *insn_name;
+  unsigned char major_opcode;
+  unsigned char sub_opcode;
+  unsigned char syntax_class = 0;
+  unsigned char syntax_class_modifiers = 0;
+  unsigned char suffix_class = 0;
+  unsigned int i;
+
+  SKIP_WHITESPACE ();
+
+  /* 1st: get instruction name.  */
+  p = input_line_pointer;
+  c = get_symbol_name (&p);
+
+  insn_name = xstrdup (p);
+  restore_line_pointer (c);
+
+  /* 2nd: get major opcode.  */
+  if (*input_line_pointer != ',')
+    {
+      as_bad (_("expected comma after instruction name"));
+      ignore_rest_of_line ();
+      return;
+    }
+  input_line_pointer++;
+  major_opcode = get_absolute_expression ();
+
+  /* 3rd: get sub-opcode.  */
+  SKIP_WHITESPACE ();
+
+  if (*input_line_pointer != ',')
+    {
+      as_bad (_("expected comma after major opcode"));
+      ignore_rest_of_line ();
+      return;
+    }
+  input_line_pointer++;
+  sub_opcode = get_absolute_expression ();
+
+  /* 4th: get suffix class.  */
+  SKIP_WHITESPACE ();
+
+  if (*input_line_pointer != ',')
+    {
+      as_bad ("expected comma after sub opcode");
+      ignore_rest_of_line ();
+      return;
+    }
+  input_line_pointer++;
+
+  while (1)
+    {
+      SKIP_WHITESPACE ();
+
+      for (i = 0; i < ARRAY_SIZE (suffixclass); i++)
+	{
+	  if (!strncmp (suffixclass[i].name, input_line_pointer,
+			suffixclass[i].len))
+	    {
+	      suffix_class |= suffixclass[i].class;
+	      input_line_pointer += suffixclass[i].len;
+	      break;
+	    }
+	}
+
+      if (i == ARRAY_SIZE (suffixclass))
+	{
+	  as_bad ("invalid suffix class");
+	  ignore_rest_of_line ();
+	  return;
+	}
+
+      SKIP_WHITESPACE ();
+
+      if (*input_line_pointer == '|')
+	input_line_pointer++;
+      else
+	break;
+    }
+
+  /* 5th: get syntax class and syntax class modifiers.  */
+  if (*input_line_pointer != ',')
+    {
+      as_bad ("expected comma after suffix class");
+      ignore_rest_of_line ();
+      return;
+    }
+  input_line_pointer++;
+
+  while (1)
+    {
+      SKIP_WHITESPACE ();
+
+      for (i = 0; i < ARRAY_SIZE (syntaxclassmod); i++)
+	{
+	  if (!strncmp (syntaxclassmod[i].name,
+			input_line_pointer,
+			syntaxclassmod[i].len))
+	    {
+	      syntax_class_modifiers |= syntaxclassmod[i].class;
+	      input_line_pointer += syntaxclassmod[i].len;
+	      break;
+	    }
+	}
+
+      if (i == ARRAY_SIZE (syntaxclassmod))
+	{
+	  for (i = 0; i < ARRAY_SIZE (syntaxclass); i++)
+	    {
+	      if (!strncmp (syntaxclass[i].name,
+			    input_line_pointer,
+			    syntaxclass[i].len))
+		{
+		  syntax_class |= syntaxclass[i].class;
+		  input_line_pointer += syntaxclass[i].len;
+		  break;
+		}
+	    }
+
+	  if (i == ARRAY_SIZE (syntaxclass))
+	    {
+	      as_bad ("missing syntax class");
+	      ignore_rest_of_line ();
+	      return;
+	    }
+	}
+
+      SKIP_WHITESPACE ();
+
+      if (*input_line_pointer == '|')
+	input_line_pointer++;
+      else
+	break;
+    }
+
+  demand_empty_rest_of_line ();
+
+  einsn->name   = insn_name;
+  einsn->major  = major_opcode;
+  einsn->minor  = sub_opcode;
+  einsn->syntax = syntax_class;
+  einsn->modsyn = syntax_class_modifiers;
+  einsn->suffix = suffix_class;
+  einsn->flags  = syntax_class
+    | (syntax_class_modifiers & ARC_OP1_IMM_IMPLIED ? 0x10 : 0);
+}
+
+/* Generate an extension section.  */
+
+static int
+arc_set_ext_seg (void)
+{
+  if (!arcext_section)
+    {
+      arcext_section = subseg_new (".arcextmap", 0);
+      bfd_set_section_flags (stdoutput, arcext_section,
+			     SEC_READONLY | SEC_HAS_CONTENTS);
+    }
+  else
+    subseg_set (arcext_section, 0);
+  return 1;
+}
+
+/* Create an extension instruction description in the arc extension
+   section of the output file.
+   The structure for an instruction is like this:
+   [0]: Length of the record.
+   [1]: Type of the record.
+
+   [2]: Major opcode.
+   [3]: Sub-opcode.
+   [4]: Syntax (flags).
+   [5]+ Name instruction.
+
+   The sequence is terminated by an empty entry.  */
+
+static void
+create_extinst_section (extInstruction_t *einsn)
+{
+
+  segT old_sec    = now_seg;
+  int old_subsec  = now_subseg;
+  char *p;
+  int name_len    = strlen (einsn->name);
+
+  arc_set_ext_seg ();
+
+  p = frag_more (1);
+  *p = 5 + name_len + 1;
+  p = frag_more (1);
+  *p = EXT_INSTRUCTION;
+  p = frag_more (1);
+  *p = einsn->major;
+  p = frag_more (1);
+  *p = einsn->minor;
+  p = frag_more (1);
+  *p = einsn->flags;
+  p = frag_more (name_len + 1);
+  strcpy (p, einsn->name);
+
+  subseg_set (old_sec, old_subsec);
+}
+
+/* Handler .extinstruction pseudo-op.  */
+
+static void arc_extinsn (int ignore ATTRIBUTE_UNUSED)
+{
+  extInstruction_t einsn;
+  struct arc_opcode *arc_ext_opcodes;
+  const char *errmsg = NULL;
+  unsigned char moplow, mophigh;
+
+  memset (&einsn, 0, sizeof (einsn));
+  tokenize_extinsn (&einsn);
+
+  /* Check if the name is already used.  */
+  if (arc_find_opcode (einsn.name))
+    as_warn (_("Pseudocode already used %s"), einsn.name);
+
+  /* Check the opcode ranges.  */
+  moplow = 0x05;
+  mophigh = (arc_target & (ARC_OPCODE_ARCv2EM
+			   | ARC_OPCODE_ARCv2HS)) ? 0x07 : 0x0a;
+
+  if ((einsn.major > mophigh) || (einsn.major < moplow))
+    as_fatal (_("major opcode not in range [0x%02x - 0x%02x]"), moplow, mophigh);
+
+  if ((einsn.minor > 0x3f) && (einsn.major != 0x0a)
+      && (einsn.major != 5) && (einsn.major != 9))
+    as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
+
+  switch (einsn.syntax & (ARC_SYNTAX_3OP | ARC_SYNTAX_2OP))
+    {
+    case ARC_SYNTAX_3OP:
+      if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
+	as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
+      break;
+    case ARC_SYNTAX_2OP:
+      if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
+	as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
+      break;
+    default:
+      break;
+    }
+
+  arc_ext_opcodes = arcExtMap_genOpcode (&einsn, arc_target, &errmsg);
+  if (arc_ext_opcodes == NULL)
+    {
+      if (errmsg)
+	as_fatal ("%s", errmsg);
+      else
+	as_fatal (_("Couldn't generate extension instruction opcodes"));
+    }
+  else if (errmsg)
+    as_warn ("%s", errmsg);
+
+  /* Insert the extension instruction.  */
+  arc_insert_opcode ((const struct arc_opcode *) arc_ext_opcodes);
+
+  create_extinst_section (&einsn);
+}
+
+/* Local variables:
+   eval: (c-set-style "gnu")
+   indent-tabs-mode: t
+   End:  */
diff --git a/gas/doc/c-arc.texi b/gas/doc/c-arc.texi
index 4824027..a237285 100644
--- a/gas/doc/c-arc.texi
+++ b/gas/doc/c-arc.texi
@@ -320,7 +320,7 @@ machine directives:
 @table @code
 
 @cindex @code{lcomm} directive
-@item .lcomm @var{symbol} , @var{length}[, @var{alignment}]
+@item .lcomm @var{symbol}, @var{length}[, @var{alignment}]
 Reserve @var{length} (an absolute expression) bytes for a local common
 denoted by @var{symbol}.  The section and value of @var{symbol} are
 those of the new local common.  The addresses are allocated in the bss
@@ -336,11 +336,11 @@ largest power of two less than or equal to the size of the symbol, up
 to a maximum of 16.
 
 @cindex @code{lcommon} directive
-@item .lcommon @var{symbol} , @var{length}[, @var{alignment}]
+@item .lcommon @var{symbol}, @var{length}[, @var{alignment}]
 The same as @code{lcomm} directive.
 
-@cindex @code{cpu} directive, ARC
-@cindex @code{cpu} directive, ARC
+@cindex @code{cpu} directive
+@item .cpu @var{cpu}
 The @code{.cpu} directive must be followed by the desired core
 version.  Permitted values for CPU are:
 @table @code
@@ -361,6 +361,93 @@ Assemble for the ARC HS instruction set.
 Note: the @code{.cpu} directive overrides the command line option
 @code{-mcpu=@var{cpu}}; a warning is emitted when the version is not
 consistent between the two.
+
+@item .extInstruction @var{name}, @var{opcode}, @var{subopcode}, @var{suffixclass}, @var{syntaxclass}
+@cindex @code{extInstruction} directive
+ARC allows the user to specify extension instructions.  These
+extension instructions are not macros; the assembler creates encodings
+for use of these instructions according to the specification by the
+user.
+
+The first argument, @var{name}, gives the name of the instruction.
+
+The second argument, @var{opcode}, is the opcode to be used (bits 31:27
+in the encoding).
+
+The third argument, @var{subopcode}, is the sub-opcode to be used, but
+the correct value also depends on the fifth argument,
+@var{syntaxclass}
+
+The fourth argument, @var{suffixclass}, determines the kinds of
+suffixes to be allowed.  Valid values are:
+@table @code
+@item SUFFIX_NONE
+No suffixes are permitted;
+
+@item SUFFIX_COND
+Conditional suffixes are permitted;
+
+@item SUFFIX_FLAG
+Flag setting suffixes are permitted.
+
+@item SUFFIX_COND|SUFFIX_FLAG
+Both conditional and flag setting suffices are permitted.
+
+@end table
+
+The fifth and final argument, @var{syntaxclass}, determines the syntax
+class for the instruction.  It can have the following values:
+@table @code
+@item SYNTAX_2OP
+Two Operand Instruction;
+
+@item SYNTAX_3OP
+Three Operand Instruction.
+@end table
+
+The syntax class may be followed by @samp{|} and one of the following
+modifiers.
+@table @code
+
+@item OP1_MUST_BE_IMM
+Modifies syntax class @code{SYNTAX_3OP}, specifying that the first
+operand of a three-operand instruction must be an immediate (i.e., the
+result is discarded).  This is usually used to set the flags using
+specific instructions and not retain results.
+
+@item OP1_IMM_IMPLIED
+Modifies syntax class @code{SYNTAX_20P}, specifying that there is an
+implied immediate destination operand which does not appear in the
+syntax.
+
+For example, if the source code contains an instruction like:
+@example
+inst r1,r2
+@end example
+the first argument is an implied immediate (that is, the result is
+discarded).  This is the same as though the source code were: inst
+0,r1,r2.
+
+@end table
+
+For example, defining a 64-bit multiplier with immediate operands:
+@example
+	.extInstruction  mp64, 0x07, 0x2d, SUFFIX_COND|SUFFIX_FLAG,
+			 SYNTAX_3OP|OP1_MUST_BE_IMM
+@end example
+which specifies an extension instruction named @code{mp64} with 3
+operands.  It sets the flags and can be used with a condition code,
+for which the first operand is an immediate, i.e. equivalent to
+discarding the result of the operation.
+
+A two operands instruction variant would be:
+@example
+	.extInstruction mul64, 0x07, 0x2d, SUFFIX_COND,
+	SYNTAX_2OP|OP1_IMM_IMPLIED
+@end example
+which describes a two operand instruction with an implicit first
+immediate operand.  The result of this operation would be discarded.
+
 @end table
 
 @node ARC Modifiers
diff --git a/gas/testsuite/gas/arc/textinsn-errors.d b/gas/testsuite/gas/arc/textinsn-errors.d
new file mode 100644
index 0000000..b2f4a71
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn-errors.d
@@ -0,0 +1 @@
+#error-output: textinsn-errors.err
diff --git a/gas/testsuite/gas/arc/textinsn-errors.err b/gas/testsuite/gas/arc/textinsn-errors.err
new file mode 100644
index 0000000..2d99325
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn-errors.err
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*:1: Warning: Suffix SUFFIX_COND ignored
diff --git a/gas/testsuite/gas/arc/textinsn-errors.s b/gas/testsuite/gas/arc/textinsn-errors.s
new file mode 100644
index 0000000..87417f2
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn-errors.s
@@ -0,0 +1 @@
+        .extInstruction myinsn0, 0x07, 0x2d, SUFFIX_FLAG|SUFFIX_COND, SYNTAX_2OP
diff --git a/gas/testsuite/gas/arc/textinsn2op.d b/gas/testsuite/gas/arc/textinsn2op.d
new file mode 100644
index 0000000..52d52ce
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn2op.d
@@ -0,0 +1,24 @@
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+   0:	382f 006d           	myinsn	r0,r1
+   4:	3b2f 372d           	myinsn	fp,sp
+   8:	386f 002d           	myinsn	r0,0
+   c:	392f 0fad ffff ffff 	myinsn	r1,0xffffffff
+  14:	3e2f 70ad           	myinsn	0,r2
+  18:	3c2f 0fad 0000 00ff 	myinsn	r4,0xff
+  20:	3e2f 0fad ffff ff00 	myinsn	r6,0xffffff00
+  28:	382f 1fad 0000 0100 	myinsn	r8,0x100
+  30:	392f 1fad ffff feff 	myinsn	r9,0xfffffeff
+  38:	3b2f 1fad 4242 4242 	myinsn	r11,0x42424242
+  40:	382f 0fad 0000 0000 	myinsn	r0,0
+			44: R_ARC_32_ME	foo
+  48:	382f 806d           	myinsn.f	r0,r1
+  4c:	3a6f 806d           	myinsn.f	r2,0x1
+  50:	3e2f f12d           	myinsn.f	0,r4
+  54:	3d2f 8fad 0000 0200 	myinsn.f	r5,0x200
diff --git a/gas/testsuite/gas/arc/textinsn2op.s b/gas/testsuite/gas/arc/textinsn2op.s
new file mode 100644
index 0000000..ec96c70
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn2op.s
@@ -0,0 +1,22 @@
+# Insn 3 .extInstruction test
+	.extInstruction myinsn, 0x07, 0x2d, SUFFIX_FLAG, SYNTAX_2OP
+
+        myinsn r0,r1
+        myinsn fp,sp
+
+        myinsn r0,0
+        myinsn r1,-1
+        myinsn 0,r2
+        myinsn r4,255
+        myinsn r6,-256
+
+        myinsn r8,256
+        myinsn r9,-257
+        myinsn r11,0x42424242
+
+        myinsn r0,foo
+
+        myinsn.f r0,r1
+        myinsn.f r2,1
+        myinsn.f 0,r4
+        myinsn.f r5,512
diff --git a/gas/testsuite/gas/arc/textinsn2op01.d b/gas/testsuite/gas/arc/textinsn2op01.d
new file mode 100644
index 0000000..ea14df7
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn2op01.d
@@ -0,0 +1,27 @@
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+   0:	382d 007e           	myinsn	r0,r1
+   4:	3b2d 373e           	myinsn	fp,sp
+   8:	386d 003e           	myinsn	r0,0
+   c:	392d 0fbe ffff ffff 	myinsn	r1,0xffffffff
+  14:	3eed 7080 0000 0000 	myinsn	0,r2
+  1c:	3c2d 0fbe 0000 00ff 	myinsn	r4,0xff
+  24:	3e2d 0fbe ffff ff00 	myinsn	r6,0xffffff00
+  2c:	382d 1fbe 0000 0100 	myinsn	r8,0x100
+  34:	392d 1fbe ffff feff 	myinsn	r9,0xfffffeff
+  3c:	3b2d 1fbe 4242 4242 	myinsn	r11,0x42424242
+  44:	382d 0fbe 0000 0000 	myinsn	r0,0
+			48: R_ARC_32_ME	foo
+  4c:	382d 807e           	myinsn.f	r0,r1
+  50:	3a6d 807e           	myinsn.f	r2,0x1
+  54:	3eed f100 0000 0000 	myinsn.f	0,r4
+  5c:	3d2d 8fbe 0000 0200 	myinsn.f	r5,0x200
+  64:	3eed f102 0000 0000 	myinsn.ne.f	0,r4
+  6c:	3eed ff85 dead beef 	myinsn.c.f	0xdeadbeef,0xdeadbeef
+  74:	3eed f0a6 dead beef 	myinsn.nc.f	0xdeadbeef,0x2
diff --git a/gas/testsuite/gas/arc/textinsn2op01.s b/gas/testsuite/gas/arc/textinsn2op01.s
new file mode 100644
index 0000000..dbd5b24
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn2op01.s
@@ -0,0 +1,26 @@
+# Insn 2op .extInstruction test
+	.extInstruction myinsn, 0x07, 0x2d, SUFFIX_FLAG|SUFFIX_COND, SYNTAX_2OP|OP1_IMM_IMPLIED
+
+        myinsn r0,r1
+        myinsn fp,sp
+
+        myinsn r0,0
+        myinsn r1,-1
+        myinsn 0,r2
+        myinsn r4,255
+        myinsn r6,-256
+
+        myinsn r8,256
+        myinsn r9,-257
+        myinsn r11,0x42424242
+
+        myinsn r0,foo
+
+        myinsn.f r0,r1
+        myinsn.f r2,1
+        myinsn.f 0,r4
+        myinsn.f r5,512
+
+	myinsn.ne.f 0,r4
+	myinsn.c.f  0xdeadbeef, 0xdeadbeef
+	myinsn.nc.f 0xdeadbeef, 0x02
diff --git a/gas/testsuite/gas/arc/textinsn3op.d b/gas/testsuite/gas/arc/textinsn3op.d
new file mode 100644
index 0000000..abf69ff
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn3op.d
@@ -0,0 +1,63 @@
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+   0:	392d 0080           	myinsn	r0,r1,r2
+   4:	3b2d 371a           	myinsn	gp,fp,sp
+   8:	3e2d 37dd           	myinsn	ilink,r30,blink
+   c:	396d 0000           	myinsn	r0,r1,0
+  10:	3e2d 7080 0000 0000 	myinsn	r0,0,r2
+  18:	392d 00be           	myinsn	0,r1,r2
+  1c:	392d 0f80 ffff ffff 	myinsn	r0,r1,0xffffffff
+  24:	3e2d 7080 ffff ffff 	myinsn	r0,0xffffffff,r2
+  2c:	392d 0f80 0000 00ff 	myinsn	r0,r1,0xff
+  34:	3e2d 7080 0000 00ff 	myinsn	r0,0xff,r2
+  3c:	392d 0f80 ffff ff00 	myinsn	r0,r1,0xffffff00
+  44:	3e2d 7080 ffff ff00 	myinsn	r0,0xffffff00,r2
+  4c:	392d 0f80 0000 0100 	myinsn	r0,r1,0x100
+  54:	3e2d 7080 ffff feff 	myinsn	r0,0xfffffeff,r2
+  5c:	3e2d 7f80 0000 0100 	myinsn	r0,0x100,0x100
+  64:	392d 0f80 0000 0000 	myinsn	r0,r1,0
+			68: R_ARC_32_ME	foo
+  6c:	38ed 0080           	myinsn	r0,r0,r2
+  70:	3bed 0140           	myinsn	r3,r3,r5
+  74:	3eed 0201           	myinsn.eq	r6,r6,r8
+  78:	39ed 12c1           	myinsn.eq	r9,r9,r11
+  7c:	3ced 1382           	myinsn.ne	r12,r12,r14
+  80:	3fed 1442           	myinsn.ne	r15,r15,r17
+  84:	3aed 2503           	myinsn.p	r18,r18,r20
+  88:	3ded 25c3           	myinsn.p	r21,r21,r23
+  8c:	38ed 3684           	myinsn.n	r24,r24,gp
+  90:	3bed 3744           	myinsn.n	fp,fp,ilink
+  94:	3eed 37c5           	myinsn.c	r30,r30,blink
+  98:	3bed 00c5           	myinsn.c	r3,r3,r3
+  9c:	3bed 0205           	myinsn.c	r3,r3,r8
+  a0:	3bed 0106           	myinsn.nc	r3,r3,r4
+  a4:	3ced 0106           	myinsn.nc	r4,r4,r4
+  a8:	3ced 01c6           	myinsn.nc	r4,r4,r7
+  ac:	3ced 0147           	myinsn.v	r4,r4,r5
+  b0:	3ded 0147           	myinsn.v	r5,r5,r5
+  b4:	3ded 0148           	myinsn.nv	r5,r5,r5
+  b8:	3ded 0148           	myinsn.nv	r5,r5,r5
+  bc:	3eed 0009           	myinsn.gt	r6,r6,r0
+  c0:	38ed 002a           	myinsn.ge	r0,r0,0
+  c4:	39ed 006b           	myinsn.lt	r1,r1,0x1
+  c8:	3bed 00ed           	myinsn.hi	r3,r3,0x3
+  cc:	3ced 012e           	myinsn.ls	r4,r4,0x4
+  d0:	3ded 016f           	myinsn.pnz	r5,r5,0x5
+  d4:	392d 8080           	myinsn.f	r0,r1,r2
+  d8:	396d 8040           	myinsn.f	r0,r1,0x1
+  dc:	3e2d f080 0000 0001 	myinsn.f	r0,0x1,r2
+  e4:	392d 80be           	myinsn.f	0,r1,r2
+  e8:	392d 8f80 0000 0200 	myinsn.f	r0,r1,0x200
+  f0:	3e2d f080 0000 0200 	myinsn.f	r0,0x200,r2
+  f8:	39ed 8081           	myinsn.eq.f	r1,r1,r2
+  fc:	38ed 8022           	myinsn.ne.f	r0,r0,0
+ 100:	3aed 808b           	myinsn.lt.f	r2,r2,r2
+ 104:	3eed f0a9 0000 0001 	myinsn.gt.f	0,0x1,0x2
+ 10c:	3eed ff8c 0000 0200 	myinsn.le.f	0,0x200,0x200
+ 114:	3eed f0aa 0000 0200 	myinsn.ge.f	0,0x200,0x2
diff --git a/gas/testsuite/gas/arc/textinsn3op.s b/gas/testsuite/gas/arc/textinsn3op.s
new file mode 100644
index 0000000..a07aa9d
--- /dev/null
+++ b/gas/testsuite/gas/arc/textinsn3op.s
@@ -0,0 +1,64 @@
+# Insn 3op .extInstruction test
+	.extInstruction myinsn, 0x07, 0x2d, SUFFIX_FLAG|SUFFIX_COND, SYNTAX_3OP
+
+	myinsn r0,r1,r2
+	myinsn r26,fp,sp
+	myinsn ilink1,ilink2,blink
+
+	myinsn r0,r1,0
+	myinsn r0,0,r2
+	myinsn 0,r1,r2
+	myinsn r0,r1,-1
+	myinsn r0,-1,r2
+	myinsn r0,r1,255
+	myinsn r0,255,r2
+	myinsn r0,r1,-256
+	myinsn r0,-256,r2
+
+	myinsn r0,r1,256
+	myinsn r0,-257,r2
+
+	myinsn r0,256,256
+
+	myinsn r0,r1,foo
+
+	myinsn.al r0,r0,r2
+	myinsn.ra r3,r3,r5
+	myinsn.eq r6,r6,r8
+	myinsn.z  r9,r9,r11
+	myinsn.ne r12,r12,r14
+	myinsn.nz r15,r15,r17
+	myinsn.pl r18,r18,r20
+	myinsn.p  r21,r21,r23
+	myinsn.mi r24,r24,r26
+	myinsn.n  r27,r27,r29
+	myinsn.cs r30,r30,r31
+	myinsn.c  r3,r3,r3
+	myinsn.lo r3,r3,r8
+	myinsn.cc r3,r3,r4
+	myinsn.nc r4,r4,r4
+	myinsn.hs r4,r4,r7
+	myinsn.vs r4,r4,r5
+	myinsn.v  r5,r5,r5
+	myinsn.vc r5,r5,r5
+	myinsn.nv r5,r5,r5
+	myinsn.gt r6,r6,r0
+	myinsn.ge r0,r0,0
+	myinsn.lt r1,r1,1
+	myinsn.hi r3,r3,3
+	myinsn.ls r4,r4,4
+	myinsn.pnz r5,r5,5
+
+	myinsn.f r0,r1,r2
+	myinsn.f r0,r1,1
+	myinsn.f r0,1,r2
+	myinsn.f 0,r1,r2
+	myinsn.f r0,r1,512
+	myinsn.f r0,512,r2
+
+	myinsn.eq.f r1,r1,r2
+	myinsn.ne.f r0,r0,0
+	myinsn.lt.f r2,r2,r2
+	myinsn.gt.f 0,1,2
+	myinsn.le.f 0,512,512
+	myinsn.ge.f 0,512,2
diff --git a/include/opcode/arc.h b/include/opcode/arc.h
index bc0e1ad..a98a2d6 100644
--- a/include/opcode/arc.h
+++ b/include/opcode/arc.h
@@ -130,7 +130,6 @@ struct arc_opcode
    in the order in which the disassembler should consider
    instructions.  */
 extern const struct arc_opcode arc_opcodes[];
-extern const unsigned arc_num_opcodes;
 
 /* CPU Availability.  */
 #define ARC_OPCODE_ARC600   0x0001  /* ARC 600 specific insns.  */
@@ -494,4 +493,54 @@ extern const unsigned arc_num_relax_opcodes;
 #define MINSN2OP_BU  (~(FIELDF | FIELDB (63) | FIELDC (63)))
 #define MINSN2OP_0U  (~(FIELDF | FIELDC (63)))
 
+/* Various constants used when defining an extension instruction.  */
+#define ARC_SYNTAX_3OP		(1 << 0)
+#define ARC_SYNTAX_2OP		(1 << 1)
+#define ARC_OP1_MUST_BE_IMM	(1 << 2)
+#define ARC_OP1_IMM_IMPLIED	(1 << 3)
+
+#define ARC_SUFFIX_NONE		(1 << 0)
+#define ARC_SUFFIX_COND		(1 << 1)
+#define ARC_SUFFIX_FLAG		(1 << 2)
+
+
+/* Constants needed to initialize extension instructions.  */
+extern const unsigned char flags_none[MAX_INSN_FLGS + 1];
+extern const unsigned char flags_f[MAX_INSN_FLGS + 1];
+extern const unsigned char flags_cc[MAX_INSN_FLGS + 1];
+extern const unsigned char flags_ccf[MAX_INSN_FLGS + 1];
+
+extern const unsigned char arg_none[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rarbrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zarbrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rbrbrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rarbu6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zarbu6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rbrbu6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rbrbs12[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_ralimmrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rarblimm[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zalimmrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zarblimm[MAX_INSN_ARGS + 1];
+
+extern const unsigned char arg_32bit_rbrblimm[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_ralimmu6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zalimmu6[MAX_INSN_ARGS + 1];
+
+extern const unsigned char arg_32bit_zalimms12[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_ralimmlimm[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zalimmlimm[MAX_INSN_ARGS + 1];
+
+extern const unsigned char arg_32bit_rbrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zarc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rbu6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zau6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_rblimm[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_zalimm[MAX_INSN_ARGS + 1];
+
+extern const unsigned char arg_32bit_limmrc[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_limmu6[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_limms12[MAX_INSN_ARGS + 1];
+extern const unsigned char arg_32bit_limmlimm[MAX_INSN_ARGS + 1];
+
 #endif /* OPCODE_ARC_H */
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index 5f8fa42..0a03a0f 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -102,6 +102,107 @@ special_flag_p (const char *opname,
   return 0;
 }
 
+/* Find proper format for the given opcode.  */
+static const struct arc_opcode *
+find_format (const struct arc_opcode *arc_table,
+	     unsigned *insn, int insnLen,
+	     unsigned isa_mask)
+{
+  unsigned int i = 0;
+  const struct arc_opcode *opcode = NULL;
+  const unsigned char *opidx;
+  const unsigned char *flgidx;
+
+  do {
+    bfd_boolean invalid = FALSE;
+
+    opcode = &arc_table[i++];
+
+    if (ARC_SHORT (opcode->mask) && (insnLen == 2))
+      {
+	if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
+	  continue;
+      }
+    else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
+      {
+	if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
+	  continue;
+      }
+    else
+      continue;
+
+    if ((insn[0] ^ opcode->opcode) & opcode->mask)
+      continue;
+
+    if (!(opcode->cpu & isa_mask))
+      continue;
+
+    /* Possible candidate, check the operands.  */
+    for (opidx = opcode->operands; *opidx; opidx++)
+      {
+	int value;
+	const struct arc_operand *operand = &arc_operands[*opidx];
+
+	if (operand->flags & ARC_OPERAND_FAKE)
+	  continue;
+
+	if (operand->extract)
+	  value = (*operand->extract) (insn[0], &invalid);
+	else
+	  value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
+
+	/* Check for LIMM indicator.  If it is there, then make sure
+	   we pick the right format.  */
+	if (operand->flags & ARC_OPERAND_IR
+	    && !(operand->flags & ARC_OPERAND_LIMM))
+	  {
+	    if ((value == 0x3E && insnLen == 4)
+		|| (value == 0x1E && insnLen == 2))
+	      {
+		invalid = TRUE;
+		break;
+	      }
+	  }
+      }
+
+    /* Check the flags.  */
+    for (flgidx = opcode->flags; *flgidx; flgidx++)
+      {
+	/* Get a valid flag class.  */
+	const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
+	const unsigned *flgopridx;
+	int foundA = 0, foundB = 0;
+
+	for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
+	  {
+	    const struct arc_flag_operand *flg_operand =
+	      &arc_flag_operands[*flgopridx];
+	    unsigned int value;
+
+	    value = (insn[0] >> flg_operand->shift)
+	      & ((1 << flg_operand->bits) - 1);
+	    if (value == flg_operand->code)
+	      foundA = 1;
+	    if (value)
+	      foundB = 1;
+	  }
+	if (!foundA && foundB)
+	  {
+	    invalid = TRUE;
+	    break;
+	  }
+      }
+
+    if (invalid)
+      continue;
+
+    /* The instruction is valid.  */
+    return opcode;
+  } while (opcode->mask);
+
+  return NULL;
+}
+
 /* Disassemble ARC instructions.  */
 
 static int
@@ -111,15 +212,13 @@ print_insn_arc (bfd_vma memaddr,
   bfd_byte buffer[4];
   unsigned int lowbyte, highbyte;
   int status;
-  unsigned int i;
   int insnLen = 0;
   unsigned insn[2] = { 0, 0 };
   unsigned isa_mask;
   const unsigned char *opidx;
   const unsigned char *flgidx;
   const struct arc_opcode *opcode;
-  const char *instrName;
-  int flags;
+  const extInstruction_t *einsn;
   bfd_boolean need_comma;
   bfd_boolean open_braket;
   int size;
@@ -218,7 +317,7 @@ print_insn_arc (bfd_vma memaddr,
       return size;
     }
 
-  if (   (((buffer[lowbyte] & 0xf8) > 0x38)
+  if ((((buffer[lowbyte] & 0xf8) > 0x38)
        && ((buffer[lowbyte] & 0xf8) != 0x48))
       || ((info->mach == bfd_mach_arc_arcv2)
 	  && ((buffer[lowbyte] & 0xF8) == 0x48)) /* FIXME! ugly.  */
@@ -254,110 +353,40 @@ print_insn_arc (bfd_vma memaddr,
   info->disassembler_needs_relocs = TRUE;
 
   /* Find the first match in the opcode table.  */
-  for (i = 0; i < arc_num_opcodes; i++)
-    {
-      bfd_boolean invalid = FALSE;
+  opcode = find_format (arc_opcodes, insn, insnLen, isa_mask);
 
-      opcode = &arc_opcodes[i];
-
-      if (ARC_SHORT (opcode->mask) && (insnLen == 2))
-	{
-	  if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
-	    continue;
-	}
-      else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
-	{
-	  if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
-	    continue;
-	}
-      else
-	continue;
-
-      if ((insn[0] ^ opcode->opcode) & opcode->mask)
-	continue;
-
-      if (!(opcode->cpu & isa_mask))
-	continue;
-
-      /* Possible candidate, check the operands.  */
-      for (opidx = opcode->operands; *opidx; opidx++)
+  if (!opcode)
+    {
+      /* No instruction found.  Try the extensions.  */
+      einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
+      if (einsn)
 	{
-	  int value;
-	  const struct arc_operand *operand = &arc_operands[*opidx];
-
-	  if (operand->flags & ARC_OPERAND_FAKE)
-	    continue;
-
-	  if (operand->extract)
-	    value = (*operand->extract) (insn[0], &invalid);
-	  else
-	    value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
-
-	  /* Check for LIMM indicator.  If it is there, then make sure
-	     we pick the right format.  */
-	  if (operand->flags & ARC_OPERAND_IR
-	      && !(operand->flags & ARC_OPERAND_LIMM))
+	  const char *errmsg = NULL;
+	  opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
+	  if (opcode == NULL)
 	    {
-	      if ((value == 0x3E && insnLen == 4)
-		  || (value == 0x1E && insnLen == 2))
-		{
-		  invalid = TRUE;
-		  break;
-		}
+	      (*info->fprintf_func) (info->stream,
+				     "An error occured while "
+				     "generating the extension instruction "
+				     "operations");
+	      return -1;
 	    }
-	}
 
-      /* Check the flags.  */
-      for (flgidx = opcode->flags; *flgidx; flgidx++)
+	  opcode = find_format (opcode, insn, insnLen, isa_mask);
+	  assert (opcode != NULL);
+	}
+      else
 	{
-	  /* Get a valid flag class.  */
-	  const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
-	  const unsigned *flgopridx;
-	  int foundA = 0, foundB = 0;
+	  if (insnLen == 2)
+	    (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
+	  else
+	    (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
 
-	  for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
-	    {
-	      const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
-	      unsigned int value;
-
-	      value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
-	      if (value == flg_operand->code)
-		foundA = 1;
-	      if (value)
-		foundB = 1;
-	    }
-	  if (!foundA && foundB)
-	    {
-	      invalid = TRUE;
-	      break;
-	    }
+	  info->insn_type = dis_noninsn;
+	  return insnLen;
 	}
-
-      if (invalid)
-	continue;
-
-      /* The instruction is valid.  */
-      goto found;
     }
 
-  /* No instruction found.  Try the extenssions.  */
-  instrName = arcExtMap_instName (OPCODE (insn[0]), insn[0], &flags);
-  if (instrName)
-    {
-      opcode = &arc_opcodes[0];
-      (*info->fprintf_func) (info->stream, "%s", instrName);
-      goto print_flags;
-    }
-
-  if (insnLen == 2)
-    (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
-  else
-    (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
-
-  info->insn_type = dis_noninsn;
-  return insnLen;
-
- found:
   /* Print the mnemonic.  */
   (*info->fprintf_func) (info->stream, "%s", opcode->name);
 
@@ -382,7 +411,6 @@ print_insn_arc (bfd_vma memaddr,
 
   pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
 
- print_flags:
   /* Now extract and print the flags.  */
   for (flgidx = opcode->flags; *flgidx; flgidx++)
     {
@@ -557,7 +585,9 @@ arc_get_disassembler (bfd *abfd)
 {
   /* Read the extenssion insns and registers, if any.  */
   build_ARC_extmap (abfd);
+#ifdef DEBUG
   dump_ARC_extmap ();
+#endif
 
   return print_insn_arc;
 }
diff --git a/opcodes/arc-ext.c b/opcodes/arc-ext.c
index 52f4556..45734a0 100644
--- a/opcodes/arc-ext.c
+++ b/opcodes/arc-ext.c
@@ -27,7 +27,6 @@
 #include "elf/arc.h"
 #include "libiberty.h"
 
-
 /* This module provides support for extensions to the ARC processor
    architecture.  */
 
@@ -52,15 +51,6 @@
 
 /* These types define the information stored in the table.  */
 
-struct ExtInstruction
-{
-  char			 major;
-  char			 minor;
-  char			 flags;
-  char*			 name;
-  struct ExtInstruction* next;
-};
-
 struct ExtAuxRegister
 {
   long			 address;
@@ -141,6 +131,9 @@ create_map (unsigned char *block,
 	    insn->minor = minor;
 	    insn->flags = p[4];
 	    insn->next  = *bucket;
+	    insn->suffix = 0;
+	    insn->syntax = 0;
+	    insn->modsyn = 0;
 	    *bucket = insn;
 	    break;
 	  }
@@ -285,10 +278,8 @@ ExtReadWrite_image (enum ExtReadWrite val)
 
 /* Get the name of an extension instruction.  */
 
-const char *
-arcExtMap_instName (int opcode,
-		    int insn,
-		    int *flags)
+const extInstruction_t *
+arcExtMap_insn (int opcode, int insn)
 {
   /* Here the following tasks need to be done.  First of all, the
      opcode stored in the Extension Map is the real opcode.  However,
@@ -306,7 +297,7 @@ arcExtMap_instName (int opcode,
      then un-mangle using iiiiiI else iiiiii.  */
 
   unsigned char minor;
-  struct ExtInstruction *temp;
+  extInstruction_t *temp;
 
   /* 16-bit instructions.  */
   if (0x08 <= opcode && opcode <= 0x0b)
@@ -367,8 +358,7 @@ arcExtMap_instName (int opcode,
     {
       if ((temp->major == opcode) && (temp->minor == minor))
 	{
-	  *flags = temp->flags;
-	  return temp->name;
+	  return temp;
 	}
       temp = temp->next;
     }
@@ -459,6 +449,8 @@ build_ARC_extmap (bfd *text_bfd)
       }
 }
 
+/* Debug function used to dump the ARC information fount in arcextmap
+   sections.  */
 
 void
 dump_ARC_extmap (void)
@@ -480,8 +472,20 @@ dump_ARC_extmap (void)
 
 	for (insn = arc_extension_map.instructions[i];
 	     insn != NULL; insn = insn->next)
-	    printf ("INST: %d %d %x %s\n", insn->major, insn->minor,
-		    insn->flags, insn->name);
+	  {
+	    printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
+	    if (insn->flags & ARC_SYNTAX_2OP)
+	      printf ("SYNTAX_2OP");
+	    else if (insn->flags & ARC_SYNTAX_3OP)
+	      printf ("SYNTAX_3OP");
+	    else
+	      printf ("SYNTAX_UNK");
+
+	    if (insn->flags & 0x10)
+	      printf ("|MODIFIER");
+
+	    printf (" %s\n", insn->name);
+	  }
     }
 
     for (i = 0; i < NUM_EXT_CORE; i++)
@@ -497,3 +501,267 @@ dump_ARC_extmap (void)
 	if (arc_extension_map.condCodes[i])
 	    printf ("COND: %s\n", arc_extension_map.condCodes[i]);
 }
+
+/* For a given extension instruction generate the equivalent arc
+   opcode structure.  */
+
+struct arc_opcode *
+arcExtMap_genOpcode (const extInstruction_t *einsn,
+		     unsigned arc_target,
+		     const char **errmsg)
+{
+  struct arc_opcode *q, *arc_ext_opcodes = NULL;
+  const unsigned char *lflags_f;
+  const unsigned char *lflags_ccf;
+  int count;
+
+  /* Check for the class to see how many instructions we generate.  */
+  switch (einsn->flags & (ARC_SYNTAX_3OP | ARC_SYNTAX_2OP))
+    {
+    case ARC_SYNTAX_3OP:
+      count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
+      break;
+    case ARC_SYNTAX_2OP:
+      count = (einsn->flags & 0x10) ? 7 : 6;
+      break;
+    default:
+      count = 0;
+      break;
+    }
+
+  /* Allocate memory.  */
+  arc_ext_opcodes = (struct arc_opcode *)
+    xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
+
+  if (arc_ext_opcodes == NULL)
+    {
+      *errmsg = "Virtual memory exhausted";
+      return NULL;
+    }
+
+  /* Generate the patterns.  */
+  q = arc_ext_opcodes;
+
+  if (einsn->suffix)
+    {
+      lflags_f   = flags_none;
+      lflags_ccf = flags_none;
+    }
+  else
+    {
+      lflags_f   = flags_f;
+      lflags_ccf = flags_ccf;
+    }
+
+  if (einsn->suffix & ARC_SUFFIX_COND)
+    lflags_ccf = flags_cc;
+  if (einsn->suffix & ARC_SUFFIX_FLAG)
+    {
+      lflags_f   = flags_f;
+      lflags_ccf = flags_f;
+    }
+  if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
+    lflags_ccf = flags_ccf;
+
+  if (einsn->flags & ARC_SYNTAX_2OP
+      && !(einsn->flags & 0x10))
+    {
+      /* Regular 2OP instruction.  */
+      if (einsn->suffix & ARC_SUFFIX_COND)
+	*errmsg = "Suffix SUFFIX_COND ignored";
+
+      INSERT_XOP (q, einsn->name,
+		  INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
+		  arc_target, arg_32bit_rbrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
+		  arc_target, arg_32bit_zarc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
+		  arc_target, arg_32bit_rbu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
+		  arc_target, arg_32bit_zau6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
+		  arc_target, arg_32bit_rblimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
+		  arc_target, arg_32bit_zalimm, lflags_f);
+    }
+  else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
+    {
+      /* This is actually a 3OP pattern.  The first operand is
+	 immplied and is set to zero.  */
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
+		  arc_target, arg_32bit_rbrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
+		  arc_target, arg_32bit_rbu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
+		  arc_target, arg_32bit_rblimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
+		  arc_target, arg_32bit_limmrc, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
+		  arc_target, arg_32bit_limmu6, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
+		  arc_target, arg_32bit_limms12, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
+		  arc_target, arg_32bit_limmlimm, lflags_ccf);
+    }
+  else if (einsn->flags & ARC_SYNTAX_3OP
+	   && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
+    {
+      /* Regular 3OP instruction.  */
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_ABC (einsn->major, einsn->minor),  MINSN3OP_ABC,
+		  arc_target, arg_32bit_rarbrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
+		  arc_target, arg_32bit_zarbrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
+		  arc_target, arg_32bit_rbrbrc, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_ABU (einsn->major, einsn->minor),  MINSN3OP_ABU,
+		  arc_target, arg_32bit_rarbu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
+		  arc_target, arg_32bit_zarbu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
+		  arc_target, arg_32bit_rbrbu6, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_BBS (einsn->major, einsn->minor),  MINSN3OP_BBS,
+		  arc_target, arg_32bit_rbrbs12, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_ALC (einsn->major, einsn->minor),  MINSN3OP_ALC,
+		  arc_target, arg_32bit_ralimmrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_ABL (einsn->major, einsn->minor),  MINSN3OP_ABL,
+		  arc_target, arg_32bit_rarblimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
+		  arc_target, arg_32bit_zalimmrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
+		  arc_target, arg_32bit_zarblimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
+		  arc_target, arg_32bit_zalimmrc, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
+		  arc_target, arg_32bit_rbrblimm, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_ALU (einsn->major, einsn->minor),  MINSN3OP_ALU,
+		  arc_target, arg_32bit_ralimmu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
+		  arc_target, arg_32bit_zalimmu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
+		  arc_target, arg_32bit_zalimmu6, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
+		  arc_target, arg_32bit_zalimms12, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_ALL (einsn->major, einsn->minor),  MINSN3OP_ALL,
+		  arc_target, arg_32bit_ralimmlimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
+		  arc_target, arg_32bit_zalimmlimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
+		  arc_target, arg_32bit_zalimmlimm, lflags_ccf);
+    }
+  else if (einsn->flags & ARC_SYNTAX_3OP)
+    {
+      /* 3OP instruction which accepts only zero as first
+	 argument.  */
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
+		  arc_target, arg_32bit_zarbrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
+		  arc_target, arg_32bit_zarbu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
+		  arc_target, arg_32bit_zalimmrc, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
+		  arc_target, arg_32bit_zarblimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
+		  arc_target, arg_32bit_zalimmrc, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
+		  arc_target, arg_32bit_zalimmu6, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
+		  arc_target, arg_32bit_zalimmu6, lflags_ccf);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
+		  arc_target, arg_32bit_zalimms12, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
+		  arc_target, arg_32bit_zalimmlimm, lflags_f);
+
+      INSERT_XOP (q, einsn->name,
+		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
+		  arc_target, arg_32bit_zalimmlimm, lflags_ccf);
+    }
+  else
+    {
+      *errmsg = "Unknown syntax";
+      return NULL;
+    }
+
+  /* End marker.  */
+  memset (q, 0, sizeof (*arc_ext_opcodes));
+
+  return arc_ext_opcodes;
+}
diff --git a/opcodes/arc-ext.h b/opcodes/arc-ext.h
index 9c2f4b7..fcce7e2 100644
--- a/opcodes/arc-ext.h
+++ b/opcodes/arc-ext.h
@@ -39,13 +39,14 @@
 #ifndef ARC_EXTENSIONS_H
 #define ARC_EXTENSIONS_H
 
+#include "opcode/arc.h"
+
 #define IGNORE_FIRST_OPD 1
 
 /* Define this if we do not want to encode instructions based on the
    ARCompact Programmer's Reference.  */
 #define UNMANGLED
 
-
 /* This defines the kinds of extensions which may be read from the
    ections in the executable files.  */
 enum ExtOperType
@@ -63,7 +64,6 @@ enum ExtOperType
   EXT_CORE_REGISTER_CLASS    = 9
 };
 
-
 enum ExtReadWrite
 {
   REG_INVALID,
@@ -72,6 +72,48 @@ enum ExtReadWrite
   REG_READWRITE
 };
 
+/* Macro used when generating the patterns for an extension
+   instruction.  */
+#define INSERT_XOP(OP, NAME, CODE, MASK, CPU, ARG, FLG)	\
+  do {							\
+    (OP)->name   = NAME;				\
+    (OP)->opcode = CODE;				\
+    (OP)->mask   = MASK;				\
+    (OP)->cpu    = CPU;					\
+    (OP)->class  = ARITH;				\
+    (OP)->subclass = NONE;				\
+    memcpy ((OP)->operands, (ARG), MAX_INSN_ARGS);	\
+    memcpy ((OP)->flags, (FLG), MAX_INSN_FLGS);		\
+    (OP++);						\
+  } while (0)
+
+/* Typedef to hold the extension instruction definition.  */
+typedef struct ExtInstruction
+{
+  /* Name.  */
+  char *name;
+
+  /* Major opcode.  */
+  char major;
+
+  /* Minor(sub) opcode.  */
+  char minor;
+
+  /* Flags, holds the syntax class and modifiers.  */
+  char flags;
+
+  /* Syntax class.  Use by assembler.  */
+  unsigned char syntax;
+
+  /* Syntax class modifier.  Used by assembler.  */
+  unsigned char modsyn;
+
+  /* Suffix class.  Used by assembler.  */
+  unsigned char suffix;
+
+  /* Pointer to the next extension instruction.  */
+  struct ExtInstruction* next;
+} extInstruction_t;
 
 /* Constructor function.  */
 extern void build_ARC_extmap (bfd *);
@@ -81,7 +123,10 @@ extern enum ExtReadWrite arcExtMap_coreReadWrite (int);
 extern const char * arcExtMap_coreRegName (int);
 extern const char * arcExtMap_auxRegName (long);
 extern const char * arcExtMap_condCodeName (int);
-extern const char * arcExtMap_instName (int, int, int *);
+extern const extInstruction_t *arcExtMap_insn (int, int);
+extern struct arc_opcode *arcExtMap_genOpcode (const extInstruction_t *,
+					       unsigned arc_target,
+					       const char **errmsg);
 
 /* Dump function (for debugging).  */
 extern void dump_ARC_extmap (void);
diff --git a/opcodes/arc-opc.c b/opcodes/arc-opc.c
index d667a78..028b80b 100644
--- a/opcodes/arc-opc.c
+++ b/opcodes/arc-opc.c
@@ -1136,6 +1136,11 @@ const struct arc_flag_class arc_flag_classes[] =
 
 };
 
+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:
@@ -1499,6 +1504,39 @@ const unsigned arc_num_operands = ARRAY_SIZE (arc_operands);
 const unsigned arc_Toperand = FKT_T;
 const unsigned arc_NToperand = FKT_NT;
 
+const unsigned char arg_none[]		 = { 0 };
+const unsigned char arg_32bit_rarbrc[]	 = { RA, RB, RC };
+const unsigned char arg_32bit_zarbrc[]	 = { ZA, RB, RC };
+const unsigned char arg_32bit_rbrbrc[]	 = { RB, RBdup, RC };
+const unsigned char arg_32bit_rarbu6[]	 = { RA, RB, UIMM6_20 };
+const unsigned char arg_32bit_zarbu6[]	 = { ZA, RB, UIMM6_20 };
+const unsigned char arg_32bit_rbrbu6[]	 = { RB, RBdup, UIMM6_20 };
+const unsigned char arg_32bit_rbrbs12[]	 = { RB, RBdup, SIMM12_20 };
+const unsigned char arg_32bit_ralimmrc[] = { RA, LIMM, RC };
+const unsigned char arg_32bit_rarblimm[] = { RA, RB, LIMM };
+const unsigned char arg_32bit_zalimmrc[] = { ZA, LIMM, RC };
+const unsigned char arg_32bit_zarblimm[] = { ZA, RB, LIMM };
+
+const unsigned char arg_32bit_rbrblimm[] = { RB, RBdup, LIMM };
+const unsigned char arg_32bit_ralimmu6[] = { RA, LIMM, UIMM6_20 };
+const unsigned char arg_32bit_zalimmu6[] = { ZA, LIMM, UIMM6_20 };
+
+const unsigned char arg_32bit_zalimms12[]  = { ZA, LIMM, SIMM12_20 };
+const unsigned char arg_32bit_ralimmlimm[] = { RA, LIMM, LIMMdup };
+const unsigned char arg_32bit_zalimmlimm[] = { ZA, LIMM, LIMMdup };
+
+const unsigned char arg_32bit_rbrc[]   = { RB, RC };
+const unsigned char arg_32bit_zarc[]   = { ZA, RC };
+const unsigned char arg_32bit_rbu6[]   = { RB, UIMM6_20 };
+const unsigned char arg_32bit_zau6[]   = { ZA, UIMM6_20 };
+const unsigned char arg_32bit_rblimm[] = { RB, LIMM };
+const unsigned char arg_32bit_zalimm[] = { ZA, LIMM };
+
+const unsigned char arg_32bit_limmrc[]   = { LIMM, RC };
+const unsigned char arg_32bit_limmu6[]   = { LIMM, UIMM6_20 };
+const unsigned char arg_32bit_limms12[]  = { LIMM, SIMM12_20 };
+const unsigned char arg_32bit_limmlimm[] = { LIMM, LIMMdup };
+
 /* The opcode table.
 
    The format of the opcode table is:
@@ -1539,9 +1577,9 @@ const struct arc_opcode arc_opcodes[] =
 #include "arc-tbl.h"
 #include "arc-nps400-tbl.h"
 #include "arc-ext-tbl.h"
-};
 
-const unsigned arc_num_opcodes = ARRAY_SIZE (arc_opcodes);
+  { NULL, 0, 0, 0, 0, 0, { 0 }, { 0 } }
+};
 
 /* List with special cases instructions and the applicable flags.  */
 const struct arc_flag_special arc_flag_special_cases[] =
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]