aboutsummaryrefslogtreecommitdiff
path: root/opcodes/ppc-dis.c
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2003-09-17 21:29:05 +0000
committerDavid Carlton <carlton@bactrian.org>2003-09-17 21:29:05 +0000
commit72f0e457e8dc611ddd1b08e3ff813aaec6ef18ed (patch)
treedf929f2af7e4e3c92dcf550e40af77c8e7abee27 /opcodes/ppc-dis.c
parented64f8fde6d716661977e17e16eff7602cab43f0 (diff)
downloadgdb-72f0e457e8dc611ddd1b08e3ff813aaec6ef18ed.zip
gdb-72f0e457e8dc611ddd1b08e3ff813aaec6ef18ed.tar.gz
gdb-72f0e457e8dc611ddd1b08e3ff813aaec6ef18ed.tar.bz2
2003-09-17 David Carlton <carlton@kealia.com>
* Merge with mainline; tag is carlton_dictionary-20030917-merge.
Diffstat (limited to 'opcodes/ppc-dis.c')
-rw-r--r--opcodes/ppc-dis.c107
1 files changed, 55 insertions, 52 deletions
diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
index b8b8b1a..76af4e7 100644
--- a/opcodes/ppc-dis.c
+++ b/opcodes/ppc-dis.c
@@ -30,18 +30,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
in both big and little endian mode and also for the POWER (RS/6000)
chip. */
-static int print_insn_powerpc PARAMS ((bfd_vma, struct disassemble_info *,
- int bigendian, int dialect));
+static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int);
-static int powerpc_dialect PARAMS ((struct disassemble_info *));
+struct dis_private {
+ /* Stash the result of parsing disassembler_options here. */
+ int dialect;
+};
/* Determine which set of machines to disassemble for. PPC403/601 or
BookE. For convenience, also disassemble instructions supported
by the AltiVec vector unit. */
-int
-powerpc_dialect(info)
- struct disassemble_info *info;
+static int
+powerpc_dialect (struct disassemble_info *info)
{
int dialect = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
@@ -49,40 +50,39 @@ powerpc_dialect(info)
dialect |= PPC_OPCODE_64;
if (info->disassembler_options
- && (strcmp (info->disassembler_options, "booke") == 0
- || strcmp (info->disassembler_options, "booke32") == 0
- || strcmp (info->disassembler_options, "booke64") == 0))
+ && strstr (info->disassembler_options, "booke") != NULL)
dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
- else
- if ((info->mach == bfd_mach_ppc_e500)
- || (info->disassembler_options
- && ( strcmp (info->disassembler_options, "e500") == 0
- || strcmp (info->disassembler_options, "e500x2") == 0)))
- {
- dialect |= PPC_OPCODE_BOOKE
- | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
- | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
- | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
- | PPC_OPCODE_RFMCI;
- /* efs* and AltiVec conflict. */
- dialect &= ~PPC_OPCODE_ALTIVEC;
- }
- else
- if (info->disassembler_options
- && (strcmp (info->disassembler_options, "efs") == 0))
- {
- dialect |= PPC_OPCODE_EFS;
- /* efs* and AltiVec conflict. */
- dialect &= ~PPC_OPCODE_ALTIVEC;
- }
+ else if ((info->mach == bfd_mach_ppc_e500)
+ || (info->disassembler_options
+ && strstr (info->disassembler_options, "e500") != NULL))
+ {
+ dialect |= PPC_OPCODE_BOOKE
+ | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
+ | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+ | PPC_OPCODE_RFMCI;
+ /* efs* and AltiVec conflict. */
+ dialect &= ~PPC_OPCODE_ALTIVEC;
+ }
+ else if (info->disassembler_options
+ && strstr (info->disassembler_options, "efs") != NULL)
+ {
+ dialect |= PPC_OPCODE_EFS;
+ /* efs* and AltiVec conflict. */
+ dialect &= ~PPC_OPCODE_ALTIVEC;
+ }
else
dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
| PPC_OPCODE_COMMON);
if (info->disassembler_options
- && strcmp (info->disassembler_options, "power4") == 0)
+ && strstr (info->disassembler_options, "power4") != NULL)
dialect |= PPC_OPCODE_POWER4;
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "any") != NULL)
+ dialect |= PPC_OPCODE_ANY;
+
if (info->disassembler_options)
{
if (strstr (info->disassembler_options, "32") != NULL)
@@ -91,35 +91,32 @@ powerpc_dialect(info)
dialect |= PPC_OPCODE_64;
}
+ ((struct dis_private *) &info->private_data)->dialect = dialect;
return dialect;
}
/* Print a big endian PowerPC instruction. */
int
-print_insn_big_powerpc (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
{
- return print_insn_powerpc (memaddr, info, 1, powerpc_dialect(info));
+ int dialect = ((struct dis_private *) &info->private_data)->dialect;
+ return print_insn_powerpc (memaddr, info, 1, dialect);
}
/* Print a little endian PowerPC instruction. */
int
-print_insn_little_powerpc (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
{
- return print_insn_powerpc (memaddr, info, 0, powerpc_dialect(info));
+ int dialect = ((struct dis_private *) &info->private_data)->dialect;
+ return print_insn_powerpc (memaddr, info, 0, dialect);
}
/* Print a POWER (RS/6000) instruction. */
int
-print_insn_rs6000 (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
}
@@ -127,11 +124,10 @@ print_insn_rs6000 (memaddr, info)
/* Print a PowerPC or POWER instruction. */
static int
-print_insn_powerpc (memaddr, info, bigendian, dialect)
- bfd_vma memaddr;
- struct disassemble_info *info;
- int bigendian;
- int dialect;
+print_insn_powerpc (bfd_vma memaddr,
+ struct disassemble_info *info,
+ int bigendian,
+ int dialect)
{
bfd_byte buffer[4];
int status;
@@ -140,6 +136,9 @@ print_insn_powerpc (memaddr, info, bigendian, dialect)
const struct powerpc_opcode *opcode_end;
unsigned long op;
+ if (dialect == 0)
+ dialect = powerpc_dialect (info);
+
status = (*info->read_memory_func) (memaddr, buffer, 4, info);
if (status != 0)
{
@@ -158,6 +157,7 @@ print_insn_powerpc (memaddr, info, bigendian, dialect)
/* Find the first match in the opcode table. We could speed this up
a bit by doing a binary search on the major opcode. */
opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+ again:
for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
{
unsigned long table_op;
@@ -177,9 +177,6 @@ print_insn_powerpc (memaddr, info, bigendian, dialect)
|| (opcode->flags & dialect) == 0)
continue;
- if ((dialect & PPC_OPCODE_EFS) && (opcode->flags & PPC_OPCODE_ALTIVEC))
- continue;
-
/* Make two passes over the operands. First see if any of them
have extraction functions, and, if they do, make sure the
instruction is valid. */
@@ -288,6 +285,12 @@ print_insn_powerpc (memaddr, info, bigendian, dialect)
return 4;
}
+ if ((dialect & PPC_OPCODE_ANY) != 0)
+ {
+ dialect = ~PPC_OPCODE_ANY;
+ goto again;
+ }
+
/* We could not find a match. */
(*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
@@ -295,7 +298,7 @@ print_insn_powerpc (memaddr, info, bigendian, dialect)
}
void
-print_ppc_disassembler_options (FILE * stream)
+print_ppc_disassembler_options (FILE *stream)
{
fprintf (stream, "\n\
The following PPC specific disassembler options are supported for use with\n\