Add support for .extInstruction pseudo-op.
authorClaudiu Zissulescu <claziss@synopsys.com>
Mon, 4 Apr 2016 14:03:53 +0000 (16:03 +0200)
committerClaudiu Zissulescu <claziss@synopsys.com>
Tue, 12 Apr 2016 08:06:07 +0000 (10:06 +0200)
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>
19 files changed:
gas/ChangeLog
gas/config/tc-arc.c
gas/doc/c-arc.texi
gas/testsuite/gas/arc/textinsn-errors.d [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn-errors.err [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn-errors.s [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn2op.d [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn2op.s [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn2op01.d [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn2op01.s [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn3op.d [new file with mode: 0644]
gas/testsuite/gas/arc/textinsn3op.s [new file with mode: 0644]
include/ChangeLog
include/opcode/arc.h
opcodes/ChangeLog
opcodes/arc-dis.c
opcodes/arc-ext.c
opcodes/arc-ext.h
opcodes/arc-opc.c

index 517331283e8a12ee67a4a0af1f9c25f7fb1d4032..688ffdec4bfd230f77f07cbf4992267bf978a2e6 100644 (file)
@@ -1,3 +1,28 @@
+2016-04-12  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.
+
 2016-04-12  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * config/tc-arc.c (preprocess_operands): Mark AUX symbol.
index 98cac6a3f423cd961b6c3e3dac2b38028fa544d5..3aeedb1943aea95cafe049b646066488d4966ed7 100644 (file)
@@ -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,275 @@ 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:  */
index 4824027e06f45c1c794d3e5cc6f551b5d441cab4..a2372858053b6740a3fee7a0cb1cedc34bf1d847 100644 (file)
@@ -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 (file)
index 0000000..b2f4a71
--- /dev/null
@@ -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 (file)
index 0000000..2d99325
--- /dev/null
@@ -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 (file)
index 0000000..87417f2
--- /dev/null
@@ -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 (file)
index 0000000..52d52ce
--- /dev/null
@@ -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 (file)
index 0000000..ec96c70
--- /dev/null
@@ -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 (file)
index 0000000..ea14df7
--- /dev/null
@@ -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 (file)
index 0000000..dbd5b24
--- /dev/null
@@ -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 (file)
index 0000000..abf69ff
--- /dev/null
@@ -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 (file)
index 0000000..a07aa9d
--- /dev/null
@@ -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
index 4b2215fa1cf6af97a5c5eda372f745db59cb8728..87333aa679ccdcc5b60b4b488b3394ecfd3dcb95 100644 (file)
@@ -1,30 +1,47 @@
-22016-04-05  Claudiu Zissulescu  <claziss@synopsys.com>
-
-        * opcode/arc.h (DPA, DPX, SPX): New subclass enums.
-        (ARC_FPUDA): Define.
-        (arc_aux_reg): Add new field.
-
-016-04-05  Cupertino Miranda  <cmiranda@synopsys.com>
+2016-04-12  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.
+
+2016-04-05  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * opcode/arc.h (DPA, DPX, SPX): New subclass enums.
+       (ARC_FPUDA): Define.
+       (arc_aux_reg): Add new field.
+
+2016-04-05  Cupertino Miranda  <cmiranda@synopsys.com>
 
        * opcode/arc-func.h (replace_bits24): Changed.
        (replace_bits24_be): Created.
 
 2016-03-29  Claudiu Zissulescu  <claziss@synopsys.com>
 
-        * opcode/arc.h (insn_subclass_t): Add QUARKSE subclass.
-        (FIELDA, FIELDB, FIELDC, FIELDF, FIELDQ, INSN3OP, INSN2OP)
-        (INSN2OP, INSN3OP_ABC, INSN3OP_ALC, INSN3OP_ABL, INSN3OP_ALL)
-        (INSN3OP_0BC, INSN3OP_0LC, INSN3OP_0BL, INSN3OP_0LL, INSN3OP_ABU)
-        (INSN3OP_ALU, INSN3OP_0BU, INSN3OP_0LU, INSN3OP_BBS, INSN3OP_0LS)
-        (INSN3OP_CBBC, INSN3OP_CBBL, INSN3OP_C0LC, INSN3OP_C0LL)
-        (INSN3OP_CBBU, INSN3OP_C0LU, MINSN3OP_ABC, MINSN3OP_ALC)
-        (MINSN3OP_ABL, MINSN3OP_ALL, MINSN3OP_0BC, MINSN3OP_0LC)
-        (MINSN3OP_0BL, MINSN3OP_0LL, MINSN3OP_ABU, MINSN3OP_ALU)
-        (MINSN3OP_0BU, MINSN3OP_0LU, MINSN3OP_BBS, MINSN3OP_0LS)
-        (MINSN3OP_CBBC, MINSN3OP_CBBL, MINSN3OP_C0LC, MINSN3OP_C0LL)
-        (MINSN3OP_CBBU, MINSN3OP_C0LU, INSN2OP_BC, INSN2OP_BL, INSN2OP_0C)
-        (INSN2OP_0L INSN2OP_BU, INSN2OP_0U, MINSN2OP_BC, MINSN2OP_BL)
-        (MINSN2OP_0C, MINSN2OP_0L, MINSN2OP_BU, MINSN2OP_0U): Define.
+       * opcode/arc.h (insn_subclass_t): Add QUARKSE subclass.
+       (FIELDA, FIELDB, FIELDC, FIELDF, FIELDQ, INSN3OP, INSN2OP)
+       (INSN2OP, INSN3OP_ABC, INSN3OP_ALC, INSN3OP_ABL, INSN3OP_ALL)
+       (INSN3OP_0BC, INSN3OP_0LC, INSN3OP_0BL, INSN3OP_0LL, INSN3OP_ABU)
+       (INSN3OP_ALU, INSN3OP_0BU, INSN3OP_0LU, INSN3OP_BBS, INSN3OP_0LS)
+       (INSN3OP_CBBC, INSN3OP_CBBL, INSN3OP_C0LC, INSN3OP_C0LL)
+       (INSN3OP_CBBU, INSN3OP_C0LU, MINSN3OP_ABC, MINSN3OP_ALC)
+       (MINSN3OP_ABL, MINSN3OP_ALL, MINSN3OP_0BC, MINSN3OP_0LC)
+       (MINSN3OP_0BL, MINSN3OP_0LL, MINSN3OP_ABU, MINSN3OP_ALU)
+       (MINSN3OP_0BU, MINSN3OP_0LU, MINSN3OP_BBS, MINSN3OP_0LS)
+       (MINSN3OP_CBBC, MINSN3OP_CBBL, MINSN3OP_C0LC, MINSN3OP_C0LL)
+       (MINSN3OP_CBBU, MINSN3OP_C0LU, INSN2OP_BC, INSN2OP_BL, INSN2OP_0C)
+       (INSN2OP_0L INSN2OP_BU, INSN2OP_0U, MINSN2OP_BC, MINSN2OP_BL)
+       (MINSN2OP_0C, MINSN2OP_0L, MINSN2OP_BU, MINSN2OP_0U): Define.
 
 2016-03-22  Trevor Saunders  <tbsaunde+binutils@tbsaunde.org>
 
 2016-02-10  Claudiu Zissulescu  <claziss@synopsys.com>
            Janek van Oirschot  <jvanoirs@synopsys.com>
 
-        * opcode/arc.h (arc_opcode arc_relax_opcodes, arc_num_relax_opcodes):
-        Declare.
+       * opcode/arc.h (arc_opcode arc_relax_opcodes)
+       (arc_num_relax_opcodes): Declare.
 
 2016-02-09  Nick Clifton  <nickc@redhat.com>
 
index bc0e1ad510e202aeee52319437bc66c27579c90d..a98a2d67635a456cf55b42ee6eddc09f1f8f2051 100644 (file)
@@ -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 */
index 4d23c24306f715ffc89218358a4be4d00a4db926..4eec5ee9df572ff1e7ed6ddc02cd0358c193094f 100644 (file)
@@ -1,3 +1,34 @@
+2016-04-12  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.
+
 2016-04-11  Maciej W. Rozycki  <macro@imgtec.com>
 
        * mips-dis.c (print_mips16_insn_arg): Mask unused extended
 
 2016-04-05  Claudiu Zissulescu  <claziss@synopsys.com>
 
-        * arc-regs.h: Add a new subclass field.  Add double assist
-        accumulator register values.
-        * arc-tbl.h: Use DPA subclass to mark the double assist
-        instructions.  Use DPX/SPX subclas to mark the FPX instructions.
-        * arc-opc.c (RSP): Define instead of SP.
-        (arc_aux_regs): Add the subclass field.
+       * arc-regs.h: Add a new subclass field.  Add double assist
+       accumulator register values.
+       * arc-tbl.h: Use DPA subclass to mark the double assist
+       instructions.  Use DPX/SPX subclas to mark the FPX instructions.
+       * arc-opc.c (RSP): Define instead of SP.
+       (arc_aux_regs): Add the subclass field.
 
 2016-04-05  Jiong Wang  <jiong.wang@arm.com>
 
 
 2016-03-30  Claudiu Zissulescu  <claziss@synopsys.com>
 
-        * arc-regs.h (IC_RAM_ADDRESS, IC_TAG, IC_WP, IC_DATA, CONTROL0)
-        (AX2, AY2, MX2, MY2, AY0, AY1, DC_RAM_ADDR, DC_TAG, CONTROL1)
-        (RTT): Remove duplicate.
-        (LCDINSTR, LCDDATA, LCDSTAT, CC_*, PCT_COUNT*, PCT_SNAP*)
-        (PCT_CONFIG*): Remove.
-        (D1L, D1H, D2H, D2L): Define.
+       * arc-regs.h (IC_RAM_ADDRESS, IC_TAG, IC_WP, IC_DATA, CONTROL0)
+       (AX2, AY2, MX2, MY2, AY0, AY1, DC_RAM_ADDR, DC_TAG, CONTROL1)
+       (RTT): Remove duplicate.
+       (LCDINSTR, LCDDATA, LCDSTAT, CC_*, PCT_COUNT*, PCT_SNAP*)
+       (PCT_CONFIG*): Remove.
+       (D1L, D1H, D2H, D2L): Define.
 
 2016-03-29  Claudiu Zissulescu  <claziss@synopsys.com>
 
-        * arc-ext-tbl.h (dsp_fp_i2flt): Fix typo.
+       * arc-ext-tbl.h (dsp_fp_i2flt): Fix typo.
 
 2016-03-29  Claudiu Zissulescu  <claziss@synopsys.com>
 
-        * arc-tbl.h (invld07): Remove.
-        * arc-ext-tbl.h: New file.
-        * arc-dis.c (FIELDA, FIELDB, FIELDC): Remove.
-        * arc-opc.c (arc_opcodes): Add ext-tbl include.
+       * arc-tbl.h (invld07): Remove.
+       * arc-ext-tbl.h: New file.
+       * arc-dis.c (FIELDA, FIELDB, FIELDC): Remove.
+       * arc-opc.c (arc_opcodes): Add ext-tbl include.
 
 2016-03-24  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 2016-02-10  Claudiu Zissulescu  <claziss@synopsys.com>
            Janek van Oirschot  <jvanoirs@synopsys.com>
 
-        * arc-opc.c (arc_relax_opcodes, arc_num_relax_opcodes): New
-        variable.
+       * arc-opc.c (arc_relax_opcodes, arc_num_relax_opcodes): New
+       variable.
 
 2016-02-04  Nick Clifton  <nickc@redhat.com>
 
index 5f8fa42d85297611ce1bb528f95ed7e90400535d..0a03a0f305ad58a6124e2bee9e8fd8d78770ca99 100644 (file)
@@ -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;
 }
index 52f455639e0a787557676f89a8c86bf96d18736a..45734a083299e229b399d37f697cc88e01b94a39 100644 (file)
@@ -27,7 +27,6 @@
 #include "elf/arc.h"
 #include "libiberty.h"
 
-
 /* This module provides support for extensions to the ARC processor
    architecture.  */
 
 
 /* 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;
+}
index 9c2f4b7374e9549699ce4bd3ba544925dde88a8c..fcce7e2bd4ea1c81ba52fa4bb5f4bdbf9a7b38ee 100644 (file)
 #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);
index d667a78d65b45b4a435b0407d983f9ba11bc3fe2..028b80bfb5f7d906c88e979402c3d03450d7d6b4 100644 (file)
@@ -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[] =