public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <andrew.burgess@embecosm.com>
To: binutils@sourceware.org
Cc: Claudiu.Zissulescu@synopsys.com,	Cupertino.Miranda@synopsys.com,
	noamca@mellanox.com,	Andrew Burgess <andrew.burgess@embecosm.com>
Subject: [PATCH 1/3] opcodes/arc: Compute insn lengths in disassembler
Date: Thu, 07 Apr 2016 11:05:00 -0000	[thread overview]
Message-ID: <1460027127-1121-2-git-send-email-andrew.burgess@embecosm.com> (raw)
In-Reply-To: <1460027127-1121-1-git-send-email-andrew.burgess@embecosm.com>

Change the mechanism by which the instruction length is figured out in
the arc disassembler.  Previously we maintained a micro-decoder that
contained enough knowledge to figure out the instruction length.  The
problem is that as instructions are added for different arc
architectures, more and more special cases need to be added to this
micro disassembler.

This commit changes to a table based lookup for the instruction length,
the table maps from the major opcode of the instruction to the
instruction length.  The table is filled at run-time, the first time
that the table is needed.

The table is self-checking while being built, it only contains the
instructions for the current architecture being disassembled, and if
different instructions with the same major opcode have different
lengths, this will cause an error while the table is being filled.

opcodes/ChangeLog:

	* arc-dis.c (arc_insn_length): New function.
	(print_insn_arc): Use arc_insn_length.
---
 opcodes/ChangeLog |  5 ++++
 opcodes/arc-dis.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index 5f8fa42..f7cff5f 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -102,6 +102,53 @@ special_flag_p (const char *opname,
   return 0;
 }
 
+/* Calculate the instruction length for an instruction starting with MSB
+   and LSB, the most and least significant byte.  The ISA_MASK is used to
+   filter the instructions considered to only those that are part of the
+   current architecture.
+
+   The instruction lengths are calculated from the ARC_OPCODE table, and
+   cached for later use.  */
+
+static int
+arc_insn_length (unsigned isa_mask, bfd_byte msb,
+                 bfd_byte lsb ATTRIBUTE_UNUSED)
+{
+  static int tbl [32]; /* 0x00 -> 0x1f */
+  static int tbl_init = 0;
+#define MAJOR_OPCODE_VALUE(BYTE) (BYTE >> 3)
+
+  if (!tbl_init)
+    {
+      unsigned i;
+
+      tbl_init = 1;
+      memset (tbl, 0, sizeof (tbl));
+      for (i = 0; i < arc_num_opcodes; i++)
+        {
+          const struct arc_opcode *opcode;
+          bfd_byte b;
+          int is_short, len;
+          unsigned value;
+
+          opcode = &arc_opcodes[i];
+          if (!(opcode->cpu & isa_mask))
+            continue;
+
+          value = opcode->opcode;
+          is_short = ARC_SHORT (opcode->mask);
+          b = MAJOR_OPCODE_VALUE (value >> (is_short ? 8 : 24));
+          len = (is_short ? 2 : 4);
+          assert (tbl [b] == 0 || tbl [b] == len);
+          tbl [b] = len;
+        }
+    }
+
+  return tbl [MAJOR_OPCODE_VALUE (msb)];
+
+#undef MAJOR_OPCODE_VALUE
+}
+
 /* Disassemble ARC instructions.  */
 
 static int
@@ -218,20 +265,19 @@ print_insn_arc (bfd_vma memaddr,
       return size;
     }
 
-  if (   (((buffer[lowbyte] & 0xf8) > 0x38)
-       && ((buffer[lowbyte] & 0xf8) != 0x48))
-      || ((info->mach == bfd_mach_arc_arcv2)
-	  && ((buffer[lowbyte] & 0xF8) == 0x48)) /* FIXME! ugly.  */
-      )
+  insnLen = arc_insn_length (isa_mask, buffer[lowbyte], buffer[highbyte]);
+  switch (insnLen)
     {
-      /* This is a short instruction.  */
-      insnLen = 2;
+    case 2:
       insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
-    }
-  else
-    {
-      insnLen = 4;
+      break;
 
+    default:
+      /* An unknown instruction is treated as being length 4.  This is
+         possibly not the best solution, but matches the behaviour that was
+         in place before the table based instruction length look-up was
+         introduced.  */
+    case 4:
       /* This is a long instruction: Read the remaning 2 bytes.  */
       status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
       if (status != 0)
@@ -240,6 +286,7 @@ print_insn_arc (bfd_vma memaddr,
 	  return -1;
 	}
       insn[0] = ARRANGE_ENDIAN (info, buffer);
+      break;
     }
 
   /* Set some defaults for the insn info.  */
-- 
2.5.1

  parent reply	other threads:[~2016-04-07 11:05 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-12 11:00 [PATCHv2 0/3] ARC: Add another group of nps instructions Andrew Burgess
2016-04-07 11:05 ` [PATCH " Andrew Burgess
2016-04-07 11:05   ` [PATCH 2/3] bfd/arc: Rename enum entries to avoid conflicts Andrew Burgess
2016-04-07 11:20     ` Claudiu Zissulescu
2016-04-07 11:05   ` Andrew Burgess [this message]
2016-04-07 11:27     ` [PATCH 1/3] opcodes/arc: Compute insn lengths in disassembler Claudiu Zissulescu
2016-04-12  9:27     ` Claudiu Zissulescu
2016-04-07 11:05   ` [PATCH 3/3] arc/nps400 : New cmem instructions and associated relocation Andrew Burgess
2016-04-11 12:55     ` Cupertino Miranda
2016-04-12 11:00   ` [PATCHv2 1/3] opcodes/arc: Move instruction length logic to new function Andrew Burgess
2016-04-12 12:27     ` Claudiu Zissulescu
2016-04-13 13:32     ` Nick Clifton
2016-04-13 14:41       ` Andrew Burgess
2016-04-13 15:30         ` Nick Clifton
2016-04-14 12:40           ` Andrew Burgess
2016-04-14 14:45             ` Nick Clifton
2016-04-12 11:00   ` [PATCHv2 2/3] bfd/arc: Rename enum entries to avoid conflicts Andrew Burgess
2016-04-13 13:34     ` Nick Clifton
2016-04-12 11:00   ` [PATCHv2 3/3] arc/nps400 : New cmem instructions and associated relocation Andrew Burgess
2016-04-13 13:37     ` Nick Clifton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1460027127-1121-2-git-send-email-andrew.burgess@embecosm.com \
    --to=andrew.burgess@embecosm.com \
    --cc=Claudiu.Zissulescu@synopsys.com \
    --cc=Cupertino.Miranda@synopsys.com \
    --cc=binutils@sourceware.org \
    --cc=noamca@mellanox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).