include/
authorAlan Modra <amodra@gmail.com>
Thu, 15 Mar 2012 12:58:48 +0000 (12:58 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 15 Mar 2012 12:58:48 +0000 (12:58 +0000)
* dis-asm.h (disassemble_init_powerpc): Declare.
opcodes/
* disassemble.c (disassemble_init_for_target): Handle ppc init.
* ppc-dis.c (private): New var.
(powerpc_init_dialect): Don't return calloc failure, instead use
private.
(PPC_OPCD_SEGS, PPC_OP_TO_SEG): Define.
(powerpc_opcd_indices): New array.
(disassemble_init_powerpc): New function.
(print_insn_big_powerpc): Don't init dialect here.
(print_insn_little_powerpc): Likewise.
(print_insn_powerpc): Start search using powerpc_opcd_indices.

include/ChangeLog
include/dis-asm.h
opcodes/ChangeLog
opcodes/disassemble.c
opcodes/ppc-dis.c

index e722835785f29622a015ba07c3bef5b33abbb459..c5b84b57996befa55f07720a51e4854c9bfca167 100644 (file)
@@ -1,3 +1,7 @@
+2012-03-15  Alan Modra  <amodra@gmail.com>
+
+       * dis-asm.h (disassemble_init_powerpc): Declare.
+
 2009-11-06  Jonas Maebe  <jonas.maebe@elis.ugent.be>
 
        Add DWARF attribute value for the "Borland fastcall" calling
index d2334c63c468b7da7c2cbcddfcbeb1ad90d4160d..c9cbfbb321cbf8936f40d9550848df6588dc4a6b 100644 (file)
@@ -1,7 +1,7 @@
 /* Interface between the opcode library and its callers.
 
    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010,
-   2011  Free Software Foundation, Inc.
+   2011, 2012 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -314,6 +314,7 @@ extern int  get_arm_regname_num_options (void);
 extern int  set_arm_regname_option (int);
 extern int  get_arm_regnames (int, const char **, const char **, const char *const **);
 extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *);
+extern void disassemble_init_powerpc (struct disassemble_info *);
 
 /* Fetch the disassembler for a given BFD, if that support is available.  */
 extern disassembler_ftype disassembler (bfd *);
index 42a099692ef6c776e568d79a372125061ceb8671..3595faf5285bbe4e92b51885973cb0504c31361f 100644 (file)
@@ -1,3 +1,17 @@
+2012-03-15  Alan Modra  <amodra@gmail.com>
+           James Lemke  <jwlemke@codesourcery.com>
+
+       * disassemble.c (disassemble_init_for_target): Handle ppc init.
+       * ppc-dis.c (private): New var.
+       (powerpc_init_dialect): Don't return calloc failure, instead use
+       private.
+       (PPC_OPCD_SEGS, PPC_OP_TO_SEG): Define.
+       (powerpc_opcd_indices): New array.
+       (disassemble_init_powerpc): New function.
+       (print_insn_big_powerpc): Don't init dialect here.
+       (print_insn_little_powerpc): Likewise.
+       (print_insn_powerpc): Start search using powerpc_opcd_indices.
+
 2012-03-10  Edmar Wienskoski  <edmar@freescale.com>
 
        * ppc-dis.c (ppc_opts): Add entries for "e5500" and "e6500".
index 0b6313537ca6d9aeabe98711b363b9f44b7d0b28..43e1d53eb40230a1d6680e4e179a626842dc06fd 100644 (file)
@@ -1,6 +1,7 @@
 /* Select disassembly routine for specified architecture.
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
@@ -565,6 +566,16 @@ disassemble_init_for_target (struct disassemble_info * info)
            cgen_bitset_set (info->insn_sets, ISA_M32C);
        }
       break;
+#endif
+#ifdef ARCH_powerpc
+    case bfd_arch_powerpc:
+#endif
+#ifdef ARCH_rs6000
+    case bfd_arch_rs6000:
+#endif
+#if defined (ARCH_powerpc) || defined (ARCH_rs6000)
+      disassemble_init_powerpc (info);
+      break;
 #endif
     default:
       break;
index e1c9f1b05c3b902223dcc7b82ec4589d91026cfd..d2cd2e59166fd6f36e222b5d886e3f5422ad3eca 100644 (file)
@@ -38,7 +38,7 @@ struct dis_private
 {
   /* Stash the result of parsing disassembler_options here.  */
   ppc_cpu_t dialect;
-};
+} private;
 
 #define POWERPC_DIALECT(INFO) \
   (((struct dis_private *) ((INFO)->private_data))->dialect)
@@ -217,7 +217,7 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, const char *arg)
 
 /* Determine which set of machines to disassemble for.  */
 
-static int
+static void
 powerpc_init_dialect (struct disassemble_info *info)
 {
   ppc_cpu_t dialect = 0;
@@ -225,7 +225,7 @@ powerpc_init_dialect (struct disassemble_info *info)
   struct dis_private *priv = calloc (sizeof (*priv), 1);
 
   if (priv == NULL)
-    return FALSE;
+    priv = &private;
 
   arg = info->disassembler_options;
   while (arg != NULL)
@@ -263,8 +263,34 @@ powerpc_init_dialect (struct disassemble_info *info)
 
   info->private_data = priv;
   POWERPC_DIALECT(info) = dialect;
+}
+
+#define PPC_OPCD_SEGS 64
+#define PPC_OP_TO_SEG(i) (i)
+static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS];
+
+/* Calculate opcode table indices to speed up disassembly,
+   and init dialect.  */
+
+void
+disassemble_init_powerpc (struct disassemble_info *info)
+{
+  int i;
+
+  for (i = 0; i < PPC_OPCD_SEGS; ++i)
+    powerpc_opcd_indices[i] = powerpc_num_opcodes;
 
-  return TRUE;
+  i = powerpc_num_opcodes;
+  while (--i >= 0)
+    {
+      unsigned op = PPC_OP (powerpc_opcodes[i].opcode);
+      unsigned seg = PPC_OP_TO_SEG (op);
+
+      powerpc_opcd_indices[seg] = i;
+    }
+
+  if (info->arch == bfd_arch_powerpc)
+    powerpc_init_dialect (info);
 }
 
 /* Print a big endian PowerPC instruction.  */
@@ -272,8 +298,6 @@ powerpc_init_dialect (struct disassemble_info *info)
 int
 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
 {
-  if (info->private_data == NULL && !powerpc_init_dialect (info))
-    return -1;
   return print_insn_powerpc (memaddr, info, 1, POWERPC_DIALECT(info));
 }
 
@@ -282,8 +306,6 @@ print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
 int
 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
 {
-  if (info->private_data == NULL && !powerpc_init_dialect (info))
-    return -1;
   return print_insn_powerpc (memaddr, info, 0, POWERPC_DIALECT(info));
 }
 
@@ -375,11 +397,14 @@ print_insn_powerpc (bfd_vma memaddr,
   /* Get the major opcode of the instruction.  */
   op = PPC_OP (insn);
 
-  /* Find the first match in the opcode table.  We could speed this up
-     a bit by doing a binary search on the major opcode.  */
+  /* Find the first match in the opcode table.
+     We speed this up by segmenting the opcode table and starting the search
+     at one of the segment boundaries.  */
   opcode_end = powerpc_opcodes + powerpc_num_opcodes;
  again:
-  for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
+  for (opcode = powerpc_opcodes + powerpc_opcd_indices[PPC_OP_TO_SEG (op)];
+       opcode < opcode_end;
+       ++opcode)
     {
       unsigned long table_op;
       const unsigned char *opindex;
@@ -390,10 +415,10 @@ print_insn_powerpc (bfd_vma memaddr,
       int skip_optional;
 
       table_op = PPC_OP (opcode->opcode);
-      if (op < table_op)
-       break;
       if (op > table_op)
        continue;
+      if (op < table_op)
+       break;
 
       if ((insn & opcode->mask) != opcode->opcode
          || (opcode->flags & dialect) == 0