public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/6] gas/arc: Modify structure used to hold opcodes
@ 2016-04-02 22:51 Andrew Burgess
  2016-04-02 22:51 ` [PATCH 4/6] gas/arc: Handle multiple arc_opcode chains for same mnemonic Andrew Burgess
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Andrew Burgess @ 2016-04-02 22:51 UTC (permalink / raw)
  To: binutils; +Cc: Claudiu.Zissulescu, noamca, Andrew Burgess

The assembler builds a hash to hold references to arc_opcode entries in
the arc_opcodes table.  This hash assumes that each mnemonic will always
appear in contiguous blocks within the arc_opcodes table, so all ADD
instruction will be together, all AND instructions will likewise be
together and so on.

The problem with this is that as different variations of arc are added,
then it is often more convenient to split instructions apart, so all the
base ADD instructions are together, but, variants of ADD specific to one
variation of arc are grouped with other instructions specific to that
arc variant.  The current data structures don't support this
configuration of instructions.

This commit is a first step towards addressing this problem.  In this
commit the hash table that currently holds arc_opcode pointers directly,
instead holds a pointer to a new, intermediate, data structure.  This
new data structure holds the pointer to the arc_opcode.  In this way, we
can, in a future commit support having the intermediate structure hold
multiple pointers to different arc_opcode groups.

gas/ChangeLog:

	* config/tc-arc.c (struct arc_opcode_hash_entry): New structure.
	(arc_find_opcode): New function.
	(find_special_case_pseudo): Use arc_find_opcode.
	(find_special_case_flag): Likewise.
	(assemble_tokens): Likewise.
	(md_begin): Build hash using struct arc_opcode_hash_entry.
---
 gas/ChangeLog       |  9 ++++++++
 gas/config/tc-arc.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 65 insertions(+), 10 deletions(-)

diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index 4f9c336..3c093ca 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -305,6 +305,16 @@ static struct arc_last_insn
   bfd_boolean has_delay_slot;
 } arc_last_insns[2];
 
+/* Structure to hold an entry in ARC_OPCODE_HASH.  */
+struct arc_opcode_hash_entry
+{
+  /* The number of pointers in the OPCODE list.  */
+  size_t count;
+
+  /* Points to a list of opcode pointers.  */
+  const struct arc_opcode **opcode;
+};
+
 /* Forward declaration.  */
 static void assemble_insn
   (const struct arc_opcode *, const expressionS *, int,
@@ -551,6 +561,29 @@ static bfd_boolean assembling_insn = FALSE;
 
 /* Functions implementation.  */
 
+/* Return a pointer to the first entry in ARC_OPCODE_HASH that matches
+   NAME, or NULL if there are no matching entries.  */
+
+static const struct arc_opcode *
+arc_find_opcode (const char *name)
+{
+  const struct arc_opcode_hash_entry *entry;
+  const struct arc_opcode *opcode;
+
+  entry = hash_find (arc_opcode_hash, name);
+  if (entry != NULL)
+    {
+      if (entry->count > 1)
+        as_fatal (_("unable to lookup `%s', too many opcode chains"),
+                  name);
+      opcode = *entry->opcode;
+    }
+  else
+    opcode = NULL;
+
+  return opcode;
+}
+
 /* 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.  */
@@ -1871,8 +1904,7 @@ find_special_case_pseudo (const char *opname,
       break;
     }
 
-  return (const struct arc_opcode *)
-    hash_find (arc_opcode_hash,	pseudo_insn->mnemonic_r);
+  return arc_find_opcode (pseudo_insn->mnemonic_r);
 }
 
 static const struct arc_opcode *
@@ -1908,9 +1940,7 @@ find_special_case_flag (const char *opname,
 	  flaglen = strlen (flagnm);
 	  if (strcmp (opname + oplen, flagnm) == 0)
 	    {
-	      opcode = (const struct arc_opcode *)
-		hash_find (arc_opcode_hash,
-			   arc_flag_special_opcode->name);
+              opcode = arc_find_opcode (arc_flag_special_opcode->name);
 
 	      if (*nflgs + 1 > MAX_INSN_FLGS)
 		break;
@@ -2000,7 +2030,7 @@ assemble_tokens (const char *opname,
   int cpumatch = 1;
 
   /* Search opcodes.  */
-  opcode = (const struct arc_opcode *) hash_find (arc_opcode_hash, opname);
+  opcode = arc_find_opcode (opname);
 
   /* Couldn't find opcode conventional way, try special cases.  */
   if (!opcode)
@@ -2147,12 +2177,28 @@ md_begin (void)
   for (i = 0; i < arc_num_opcodes;)
     {
       const char *name, *retval;
+      struct arc_opcode_hash_entry *entry;
 
       name = arc_opcodes[i].name;
-      retval = hash_insert (arc_opcode_hash, name, (void *) &arc_opcodes[i]);
-      if (retval)
-	as_fatal (_("internal error: can't hash opcode '%s': %s"),
-		  name, retval);
+
+      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);
+      entry->opcode [entry->count] = &arc_opcodes[i];
+      entry->count++;
 
       while (++i < arc_num_opcodes
 	     && (arc_opcodes[i].name == name
-- 
2.5.1

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2016-04-07 15:38 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-02 22:51 [PATCH 1/6] gas/arc: Modify structure used to hold opcodes Andrew Burgess
2016-04-02 22:51 ` [PATCH 4/6] gas/arc: Handle multiple arc_opcode chains for same mnemonic Andrew Burgess
2016-04-02 22:51 ` [PATCH 2/6] gas/arc: Remove preprocess_operands function Andrew Burgess
2016-04-05 14:23   ` Nick Clifton
2016-04-02 22:51 ` [PATCH 5/6] gas/arc: Allow greater range of characters into flag names Andrew Burgess
2016-04-04  7:52   ` Claudiu Zissulescu
2016-04-05 14:25   ` Nick Clifton
2016-04-02 22:51 ` [PATCH 3/6] gas/arc: Additional work to support multiple arc_opcode chains Andrew Burgess
2016-04-02 22:51 ` [PATCH 6/6] arc/nps400: Add new control instructions Andrew Burgess
2016-04-04  7:52   ` Claudiu Zissulescu
2016-04-05 14:26   ` Nick Clifton
2016-04-04  8:22 ` [PATCH 1/6] gas/arc: Modify structure used to hold opcodes Claudiu Zissulescu
2016-04-04  9:10   ` Andrew Burgess
2016-04-04 14:45     ` Claudiu Zissulescu
2016-04-07 12:51       ` Andrew Burgess
2016-04-07 13:08         ` Claudiu Zissulescu
2016-04-07 15:34           ` Nick Clifton
2016-04-07 12:57 ` [PATCHv2 4/4] arc/nps400: Add new instructions Andrew Burgess
2016-04-07 13:18   ` Claudiu Zissulescu
2016-04-07 15:38   ` Nick Clifton
2016-04-07 12:57 ` [PATCHv2 1/4] gas/arc: Modify structure used to hold opcodes Andrew Burgess
2016-04-07 13:10   ` Claudiu Zissulescu
2016-04-07 15:35   ` Nick Clifton
2016-04-07 12:57 ` [PATCHv2 3/4] gas/arc: Handle multiple arc_opcode chains for same mnemonic Andrew Burgess
2016-04-07 13:16   ` Claudiu Zissulescu
2016-04-07 15:37   ` Nick Clifton
2016-04-07 12:57 ` [PATCHv2 2/4] gas/arc: Additional work to support multiple arc_opcode chains Andrew Burgess
2016-04-07 13:14   ` Claudiu Zissulescu
2016-04-07 15:36   ` Nick Clifton
2016-04-07 12:57 ` [PATCHv2 0/4] arc/nps: Add pipeline control instructions Andrew Burgess

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