1 introduce -M histogram for ppc objdump -d
3 From: Alexandre Oliva <oliva@gnu.org>
5 With -M histogram, the disassembler counts the occurrences of each
6 opcode it encounters, and prints the totals at the end.
8 opcodes/disassemble.c | 4 ++
9 opcodes/ppc-dis.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++
10 2 files changed, 98 insertions(+)
12 diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
13 index 290dcdd100d19..961aeabfc1632 100644
14 --- a/opcodes/disassemble.c
15 +++ b/opcodes/disassemble.c
16 @@ -763,6 +763,10 @@ disassemble_free_target (struct disassemble_info *info)
19 case bfd_arch_powerpc:
21 + extern void ppc_disassemble_free_target (struct disassemble_info *);
22 + ppc_disassemble_free_target (info);
27 diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
28 index f3c84e06452dc..f5065c40ff663 100644
29 --- a/opcodes/ppc-dis.c
30 +++ b/opcodes/ppc-dis.c
33 #include "opcode/ppc.h"
34 #include "libiberty.h"
37 /* This file provides several disassembler functions, all of which use
38 the disassembler interface defined in dis-asm.h. Several functions
40 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
43 +struct opcode_counter
45 + const struct powerpc_opcode *opcode;
50 +hash_opcode_counter (const void *opcnt)
52 + const struct opcode_counter *oc = (const struct opcode_counter *)opcnt;
53 + return htab_hash_pointer (oc->opcode);
57 +same_opcode_counter (const void *opcnt1, const void *opcnt2)
59 + const struct opcode_counter *oc1 = (const struct opcode_counter *)opcnt1;
60 + const struct opcode_counter *oc2 = (const struct opcode_counter *)opcnt2;
61 + return htab_eq_pointer (oc1->opcode, oc2->opcode);
66 /* Stash the result of parsing disassembler_options here. */
69 + /* Counters for encountered opcodes. */
74 +increment_opcode_counter (struct disassemble_info *info,
75 + const struct powerpc_opcode *opcode)
77 + struct dis_private *priv = (struct dis_private *) (info->private_data);
79 + if (!priv->histogram)
82 + struct opcode_counter oc, *ocp;
85 + void **ret = htab_find_slot (priv->histogram, &oc, INSERT);
87 + if (ocp == HTAB_EMPTY_ENTRY)
89 + *ret = ocp = calloc (sizeof (oc), 1);
90 + ocp->opcode = opcode;
98 #define POWERPC_DIALECT(INFO) \
99 (((struct dis_private *) ((INFO)->private_data))->dialect)
101 @@ -381,6 +431,11 @@ powerpc_init_dialect (struct disassemble_info *info)
102 dialect |= PPC_OPCODE_64;
103 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
105 + else if (disassembler_options_cmp (opt, "histogram") == 0)
106 + priv->histogram = htab_create (17,
107 + hash_opcode_counter,
108 + same_opcode_counter,
111 /* xgettext: c-format */
112 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
113 @@ -864,6 +919,8 @@ print_insn_powerpc (bfd_vma memaddr,
114 bfd_boolean skip_optional;
117 + increment_opcode_counter (info, opcode);
119 (*info->fprintf_func) (info->stream, "%s", opcode->name);
120 /* gdb fprintf_func doesn't return count printed. */
121 blanks = 8 - strlen (opcode->name);
122 @@ -1013,3 +1070,40 @@ the -M switch:\n"));
124 fprintf (stream, "\n");
128 +dump_opcode_histogram (void **ocp, void *info_)
130 + struct opcode_counter *oc = *ocp;
131 + struct disassemble_info *info = info_;
133 + (*info->fprintf_func) (info->stream, "%8lu %s (%lx)\n",
134 + (unsigned long)oc->count,
136 + (unsigned long)oc->opcode->opcode);
141 +void ppc_disassemble_free_target (struct disassemble_info *info);
144 +ppc_disassemble_free_target (struct disassemble_info *info)
146 + struct dis_private *priv = (struct dis_private *) (info->private_data);
148 + if (priv->histogram)
150 + if (htab_elements (priv->histogram))
152 + (*info->fprintf_func) (info->stream, "\n\nOpcode histogram\n");
153 + htab_traverse (priv->histogram, dump_opcode_histogram, info);
156 + htab_delete (priv->histogram);
157 + priv->histogram = NULL;
161 + info->private_data = NULL;