2 # see https://bugs.libre-soc.org/show_bug.cgi?id=532
4 # Print a per-opcode histogram for ppc asm.
6 # Copyright 2020 Alexandre Oliva
7 # Copyright 2020 Luke Kenneth Casson Leighton
9 # This script is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3, or (at your option)
14 # This script is distributed in the hope that it will be useful, but
15 # WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this script; see the file COPYING3. If not see
21 # <http://www.gnu.org/licenses/>.
23 # Originally by Alexandre Oliva <oliva@gnu.org>.
26 # Feed this script the output of:
27 # powerpc64le-gnu-objdump -d -M raw --no-show-raw-insn ppc-prog
29 # It will print the occurrence count of each opcode,
30 # and under it, indented by one character,
31 # the occurrence count of each operand.
33 # Registers used as operands or as base addresses are counted
34 # separately; immediates and offsets are grouped per bit length;
35 # branch target offsets are grouped by range bit length.
40 insn
= re
.compile('\s+(?P<addr>[0-9a-f]+):\s+(?P<opcode>[^ \n]+) *(?P<operands>.*)[\n]?')
42 opkind
= re
.compile('(?P<immediate>-?[0-9]+)|(?P<branch>[0-9a-f]+)(?: <.*>)?|(?P<offset>-?[0-9]+)\((?P<basereg>r[0-9]+)\)')
47 match
= opkind
.fullmatch(op
)
51 elif match
['immediate'] is not None:
52 op
= "%i-bit" % int (op
).bit_length ()
53 elif match
['branch'] is not None:
54 op
= "%i-bit range" % (int (match
['branch'], 16) -
55 int(addr
, 16)).bit_length ()
56 elif match
['offset'] is not None:
57 count(ops
, match
['offset'])
60 raise "unrecognized operand kind"
67 for line
in sys
.stdin
:
68 match
= insn
.fullmatch(line
)
73 opcode
= match
['opcode']
74 operands
= match
['operands']
76 if opcode
not in histogram
:
78 histogram
[opcode
] = [1,ops
]
80 histogram
[opcode
][0] += 1
81 ops
= histogram
[opcode
][1]
84 for operand
in operands
.split(','):
90 # for each instruction print out a regcount. first, sort by instr count
91 hist
= list(histogram
.items())
92 hist
.sort(key
= (lambda x
: x
[1][0]))
94 # now print each instruction and its register usage
96 print('%6i %s:' % (x
[1][0], x
[0]))
97 ops
= list(x
[1][1].items())
98 ops
.sort(key
= (lambda x
: x
[1]))
100 # split out "-bit" from "-bit range" from "regs"
102 # first "rNs" or "anything-weird"
106 if x
[0].startswith('cr'):
108 print('\t%6i %s' % (x
[1], x
[0]))
109 # total up integer register counts
110 if not x
[0].startswith('r'):
112 if not x
[0] in intregcounts
:
113 intregcounts
[x
[0]] = 0
114 intregcounts
[x
[0]] += x
[1]
119 # now Condition Registers
123 if x
[0].startswith('cr'):
124 print('\t%6i %s' % (x
[1], x
[0]))
125 if not x
[0] in crregcounts
:
126 crregcounts
[x
[0]] = 0
127 crregcounts
[x
[0]] += x
[1]
130 # now "N-bit immediates"
132 if x
[0].endswith('-bit'):
133 print('\t%6i %s' % (x
[1], x
[0]))
136 # finally "bit-range" immediates
138 if '-bit range' in x
[0]:
139 print('\t%6i %s' % (x
[1], x
[0]))
142 # print out regs usage totals (TODO: FP)
143 for regcounts
in [intregcounts
, crregcounts
]:
144 regnums
= list(regcounts
.items())
145 regnums
.sort(key
= (lambda x
: x
[1]))
147 print('%6i %s' % (x
[1], x
[0]))