* 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.
This commit is contained in:
Alan Modra 2012-03-15 12:58:48 +00:00
parent fc3e51758a
commit b240011aba
5 changed files with 70 additions and 15 deletions

View 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

View 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 *);

View 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".

View 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;

View 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;
}
return TRUE;
#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;
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