blob: 1295a844a5b8697a1a4527fd803d4f252a983483 [file]
#!/usr/bin/python2.4
# count the number of instructions in gcc compiler's output assembler files.
import sys
PSEUDO_INSTS = {
'.file':0,
'.text':0,
'.align':0,
'.loc':0,
'.save':0,
'.vsave':0,
'@':0,
'.pad':0,
'.p2align':0,
'.size':0,
'.global':0,
'.hidden':0,
'.protected':0,
'.weak':0,
'.thumb_set':0,
}
def keyfunc(tuple):
return tuple[1]+tuple[3] # inst_size + data_size
def main():
if (len(sys.argv) != 2):
print 'gcccount.py foo.s'
return
fd = None
try:
fd = open(sys.argv[1], 'r')
except IOError:
print "Can't open file ", sys.argv[1]
return
line_no = 0
armv7 = False
have_thumb = False
thumb_mode = False
inst_count = 0
inst_size = 0
data_size = 0
functions = []
in_func = False
func_name = None
for line in fd:
line_no = line_no + 1
words = line.split()
if len(words) == 0:
continue
inst = words[0]
# label
if inst[-1] == ':':
continue
if inst in PSEUDO_INSTS:
continue
if inst == '.arch':
if len(words) > 1 and words[1] == 'armv7-a':
armv7 = True
continue
# function name
if inst == '.type':
if len(words) != 3:
message = 'ERROR: ' + line
sys.stderr.write(message)
continue
if words[2] != '%function':
continue
if in_func:
functions.append((func_name, inst_size, inst_count, data_size))
in_func = False
func_name = words[1][:-1]
in_func = True
inst_count = 0
inst_size = 0
data_size = 0
continue
# function start
if inst == '.fnstart':
in_func = True
inst_count = 0
inst_size = 0
data_size = 0
continue
# function end
if inst == '.fnend' and in_func:
in_func = False
functions.append((func_name, inst_size, inst_count, data_size))
continue
if inst == '.thumb_func':
if in_func:
in_func = False
functions.append((func_name, inst_size, inst_count, data_size))
thumb_mode = True
have_thumb = True
continue
if inst == '.code':
if len(words) != 2:
message = 'ERROR: ' + line
sys.stderr.write(message)
continue
if words[1] == '16':
thumb_mode = True
have_thumb = True
else:
thumb_mode = False
continue
if not in_func:
continue
if inst == '.word':
data_size = data_size + 4
continue
if inst == '.byte':
data_size = data_size + 1
continue
if inst == '.2byte':
data_size = data_size + 2
continue
if (inst == '.section') or (inst == '.bss') or (inst == '.data'):
if in_func:
in_func = False
functions.append((func_name, inst_size, inst_count, data_size))
continue
if inst[0] == '.':
message = 'UNRECOGNIZED TOKEN %s:%d: %s' % (sys.argv[1], line_no, line)
sys.stderr.write(message)
continue
inst_count = inst_count + 1
if thumb_mode == False:
inst_size = inst_size + 4
continue
inst = inst.lower()
if (inst == 'bl') or (inst == 'blx'):
reg = words[1].lower()
if reg[0] == 'r':
reg = reg[1:]
if reg.isdigit():
inst_size = inst_size + 2
continue
# 32bit thumb instructions
inst_size = inst_size + 4
continue
inst_size = inst_size + 2
fd.close()
if armv7 and have_thumb:
# This file contains thumb2 codes, it is difficult to count the
# instruction size. Instead readelf should be used.
# It has been noticed that sometimes the readelf output is not precise,
# so it is not used as the default method.
sys.stderr.write('WARNING: THUMB2 instructions detected, please use\n')
sys.stderr.write(' countthumb2.py foo.o\n')
sys.stderr.write('to get the code size.\n\n\n')
functions.sort(key=keyfunc, reverse=True)
for (f, inst_size, inst_count, data_size) in functions:
print ('%s size %d inst_count %d'
% (f, inst_size + data_size, inst_count))
if __name__ == '__main__':
main()