diff options
author | Alan Modra <amodra@gmail.com> | 2012-03-15 12:58:48 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2012-03-15 12:58:48 +0000 |
commit | b240011aba98dd8a0c4736a51afcea38af814200 (patch) | |
tree | 2cc895e2ccef08761fd87a9fe9fbd164c7520009 | |
parent | fc3e51758a16508acb99feaafd0b63487487bd4f (diff) | |
download | gdb-b240011aba98dd8a0c4736a51afcea38af814200.zip gdb-b240011aba98dd8a0c4736a51afcea38af814200.tar.gz gdb-b240011aba98dd8a0c4736a51afcea38af814200.tar.bz2 |
include/
* 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.
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/dis-asm.h | 3 | ||||
-rw-r--r-- | opcodes/ChangeLog | 14 | ||||
-rw-r--r-- | opcodes/disassemble.c | 13 | ||||
-rw-r--r-- | opcodes/ppc-dis.c | 51 |
5 files changed, 70 insertions, 15 deletions
diff --git a/include/ChangeLog b/include/ChangeLog index e722835..c5b84b5 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -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 diff --git a/include/dis-asm.h b/include/dis-asm.h index d2334c6..c9cbfbb 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -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 *); diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 42a0996..3595faf 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -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". diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 0b63135..43e1d53 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -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. @@ -566,6 +567,16 @@ disassemble_init_for_target (struct disassemble_info * info) } 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; } diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index e1c9f1b..d2cd2e5 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -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 |