Bug 1244: changes to images
[libreriscv.git] / lxo / 532 / binutils-ppc-insn-histogram.patch
1 introduce -M histogram for ppc objdump -d
2
3 From: Alexandre Oliva <oliva@gnu.org>
4
5 With -M histogram, the disassembler counts the occurrences of each
6 opcode it encounters, and prints the totals at the end.
7 ---
8 opcodes/disassemble.c | 4 ++
9 opcodes/ppc-dis.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++
10 2 files changed, 98 insertions(+)
11
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)
17 #endif
18 #ifdef ARCH_powerpc
19 case bfd_arch_powerpc:
20 + {
21 + extern void ppc_disassemble_free_target (struct disassemble_info *);
22 + ppc_disassemble_free_target (info);
23 + }
24 break;
25 #endif
26 #ifdef ARCH_riscv
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
31 @@ -27,6 +27,7 @@
32 #include "opintl.h"
33 #include "opcode/ppc.h"
34 #include "libiberty.h"
35 +#include "hashtab.h"
36
37 /* This file provides several disassembler functions, all of which use
38 the disassembler interface defined in dis-asm.h. Several functions
39 @@ -36,12 +37,61 @@
40 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
41 ppc_cpu_t);
42
43 +struct opcode_counter
44 +{
45 + const struct powerpc_opcode *opcode;
46 + size_t count;
47 +};
48 +
49 +static hashval_t
50 +hash_opcode_counter (const void *opcnt)
51 +{
52 + const struct opcode_counter *oc = (const struct opcode_counter *)opcnt;
53 + return htab_hash_pointer (oc->opcode);
54 +}
55 +
56 +static int
57 +same_opcode_counter (const void *opcnt1, const void *opcnt2)
58 +{
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);
62 +}
63 +
64 struct dis_private
65 {
66 /* Stash the result of parsing disassembler_options here. */
67 ppc_cpu_t dialect;
68 +
69 + /* Counters for encountered opcodes. */
70 + htab_t histogram;
71 };
72
73 +static int
74 +increment_opcode_counter (struct disassemble_info *info,
75 + const struct powerpc_opcode *opcode)
76 +{
77 + struct dis_private *priv = (struct dis_private *) (info->private_data);
78 +
79 + if (!priv->histogram)
80 + return 0;
81 +
82 + struct opcode_counter oc, *ocp;
83 + oc.opcode = opcode;
84 +
85 + void **ret = htab_find_slot (priv->histogram, &oc, INSERT);
86 + ocp = *ret;
87 + if (ocp == HTAB_EMPTY_ENTRY)
88 + {
89 + *ret = ocp = calloc (sizeof (oc), 1);
90 + ocp->opcode = opcode;
91 + }
92 +
93 + ocp->count++;
94 +
95 + return 1;
96 +}
97 +
98 #define POWERPC_DIALECT(INFO) \
99 (((struct dis_private *) ((INFO)->private_data))->dialect)
100
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)
104 dialect = new_cpu;
105 + else if (disassembler_options_cmp (opt, "histogram") == 0)
106 + priv->histogram = htab_create (17,
107 + hash_opcode_counter,
108 + same_opcode_counter,
109 + free);
110 else
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;
115 int blanks;
116
117 + increment_opcode_counter (info, opcode);
118 +
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"));
123 }
124 fprintf (stream, "\n");
125 }
126 +
127 +static int
128 +dump_opcode_histogram (void **ocp, void *info_)
129 +{
130 + struct opcode_counter *oc = *ocp;
131 + struct disassemble_info *info = info_;
132 +
133 + (*info->fprintf_func) (info->stream, "%8lu %s (%lx)\n",
134 + (unsigned long)oc->count,
135 + oc->opcode->name,
136 + (unsigned long)oc->opcode->opcode);
137 +
138 + return 1;
139 +}
140 +
141 +void ppc_disassemble_free_target (struct disassemble_info *info);
142 +
143 +void
144 +ppc_disassemble_free_target (struct disassemble_info *info)
145 +{
146 + struct dis_private *priv = (struct dis_private *) (info->private_data);
147 +
148 + if (priv->histogram)
149 + {
150 + if (htab_elements (priv->histogram))
151 + {
152 + (*info->fprintf_func) (info->stream, "\n\nOpcode histogram\n");
153 + htab_traverse (priv->histogram, dump_opcode_histogram, info);
154 + }
155 +
156 + htab_delete (priv->histogram);
157 + priv->histogram = NULL;
158 + }
159 +
160 + free (priv);
161 + info->private_data = NULL;
162 +}