diff options
Diffstat (limited to 'tools/disasm.py')
-rwxr-xr-x | tools/disasm.py | 182 |
1 files changed, 13 insertions, 169 deletions
diff --git a/tools/disasm.py b/tools/disasm.py index 31d9337..2a402f7 100755 --- a/tools/disasm.py +++ b/tools/disasm.py @@ -31,171 +31,7 @@ from binascii import b2a_hex from collections import namedtuple from etnaviv.parse_rng import parse_rng_file, format_path, BitSet, Domain - -# Register groups -# t temporary -# u uniform 0..127 -# v uniform 127..255 (this is rewritten to u in format_src) -# others are unknown -rgroups = ['t', '?1?', 'u', 'v', '?4?', '?5?', '?6?', '?7?'] -# Addressing modes -amodes = ['', 'a.x', 'a.y', 'a.z', 'a.w', '?5?', '?6?', '?7?'] -# components -COMPS = 'xyzw' - -def bitextr(val, hi, lo): - '''Extract and return bits hi..lo from value val''' - return (val >> lo) & ((1<<(hi-lo+1))-1) -def format_swiz(swiz): - swiz = [(swiz >> x)&3 for x in [0,2,4,6]] - return ''.join([COMPS[c] for c in swiz]) -def format_comps(comps): - return ''.join([COMPS[c] for c in range(4) if ((comps >> c)&1)]) - -DstOperand = namedtuple('DstOperand', ['use', 'amode', 'reg', 'comps']) -SrcOperand = namedtuple('SrcOperand', ['use', 'reg', 'swiz', 'neg', 'abs', 'amode', 'rgroup']) -TexOperand = namedtuple('TexOperand', ['id', 'amode', 'swiz']) -Instruction = namedtuple('Instruction', ['op', 'cond', 'sat', 'tex', 'dst', 'src', 'unknowns']) - -def disassemble(isa, inst): - '''Parse four 32-bit instruction words into Instruction object''' - op = bitextr(inst[0], 5, 0) - cond = bitextr(inst[0], 10, 6) - sat = bitextr(inst[0], 11, 11) # saturate - - dst = DstOperand( - use = bitextr(inst[0], 12, 12), # desination used - amode = bitextr(inst[0], 15, 13), # addressing mode - reg = bitextr(inst[0], 22, 16), # reg nr - comps = bitextr(inst[0], 26, 23) # xyzw - ) - - tex = TexOperand( - id = bitextr(inst[0], 31, 27), # texture sampler id - amode = bitextr(inst[1], 2, 0), - swiz = bitextr(inst[1], 10, 3) - ) - - src = [ - SrcOperand( - use = bitextr(inst[1], 11, 11), - reg = bitextr(inst[1], 20, 12), - swiz = bitextr(inst[1], 29, 22), - neg = bitextr(inst[1], 30, 30), - abs = bitextr(inst[1], 31, 31), - amode = bitextr(inst[2], 2, 0), # addressing mode - rgroup = bitextr(inst[2], 5, 3) # reg type (0=temp, 1=?, 2=uniform, 3=uniform) - ), - SrcOperand( - use = bitextr(inst[2], 6, 6), - reg = bitextr(inst[2], 15, 7), - swiz = bitextr(inst[2], 24, 17), - neg = bitextr(inst[2], 25, 25), - abs = bitextr(inst[2], 26, 26), - amode = bitextr(inst[2], 29, 27), - rgroup = bitextr(inst[3], 2, 0) - ), - SrcOperand( - use = bitextr(inst[3], 3, 3), - reg = bitextr(inst[3], 12, 4), - swiz = bitextr(inst[3], 21, 14), - neg = bitextr(inst[3], 22, 22), - abs = bitextr(inst[3], 23, 23), - amode = bitextr(inst[3], 27, 25), - rgroup = bitextr(inst[3], 30, 28) - ) - ] - - # Unknown fields -- these must be 0 - unknowns = [ - ('bit_1_21', bitextr(inst[1], 21, 21)), - ('bit_2_16', bitextr(inst[2], 16, 16)), - ('bit_2_28', bitextr(inst[2], 31, 28)), - ('bit_3_16', bitextr(inst[3], 13, 13)), - ('bit_3_24', bitextr(inst[3], 24, 24)), - ('bit_3_31', bitextr(inst[3], 31, 31)) - ] - return Instruction(op=op,cond=cond,sat=sat,tex=tex,dst=dst,src=src,unknowns=unknowns) - -def format_dst(isa, dst, warnings): - '''Format destination operand''' - if dst.use: - # actually, target register group depends on the instruction, but usually it's a temporary... - arg = 't%i' % (dst.reg) - if dst.amode != 0: - arg += '[%s]' % amodes[dst.amode] - if dst.comps != 15: # if not all comps selected - arg += '.' + format_comps(dst.comps) - else: - arg = 'void' # unused argument - if dst.amode != 0 or dst.reg != 0 or dst.comps != 0: - warnings.append('dst not used but fields non-zero') - - return arg - -def format_src(isa, src, warnings): - '''Format source operand''' - if src.use: - if src.rgroup == 3: # map vX to uniform u(X+128) - rgroup = 2 - reg = 128 + src.reg - else: - rgroup = src.rgroup - reg = src.reg - arg = '%s%i' % (rgroups[rgroup], reg) - if src.amode != 0: - arg += '[%s]' % amodes[src.amode] - if src.swiz != 0xe4: # if not null swizzle - arg += '.' + format_swiz(src.swiz) - # XXX is the - or the | done first? In a way, -|x| is the only ordering that makes sense. - if src.abs: - return '|' + arg + '|' - if src.neg: - return '-' + arg - else: - arg = 'void' # unused argument - if src.reg != 0 or src.swiz != 0 or src.neg != 0 or src.abs != 0 or src.amode != 0 or src.rgroup != 0: - warnings.append('src not used but fields non-zero') - return arg - -def format_tex(isa, tex, warnings): - '''Format texture operand''' - arg = 'tex%i' % (tex.id) - if tex.amode != 0: - arg += '[%i]' % amodes[tex.amode] - if tex.swiz != 0xe4: # if not null swizzle - arg += '.' + format_swiz(tex.swiz) - - return arg - -def format_instruction(isa, inst, warnings): - ''' - Format instruction as text. - ''' - atoms = [] - args = [] - atoms.append(isa.types['INST_OPCODE'].describe(inst.op)) - if inst.cond: - atoms.append(isa.types['INST_CONDITION'].describe(inst.cond)) - if inst.sat: - atoms.append(sat) - opcode = '.'.join(atoms) - - args.append(format_dst(isa, inst.dst, warnings)) - if inst.op in [0x18, 0x19, 0x1A, 0x1B, 0x1C]: - args.append(format_tex(isa, inst.tex, warnings)) - else: - if inst.tex.id != 0 or inst.tex.amode != 0 or inst.tex.swiz != 0: - warnings.append('tex not used but fields non-zero') - - for src in inst.src: - args.append(format_src(isa, src, warnings)) - - # verify that all bits in unknown are 0 - for (name,value) in inst.unknowns: - if value != 0: - warnings.append('!%s=%i!' % (name,value)) - return opcode+' '+(', '.join(args)) +from etnaviv.asm_common import format_instruction, disassemble def parse_arguments(): parser = argparse.ArgumentParser(description='Disassemble shader') @@ -203,8 +39,12 @@ def parse_arguments(): help='Shader ISA definition file (rules-ng-ng)') parser.add_argument('input', metavar='INFILE', type=str, help='Binary shader file') - #parser.add_argument('-r', dest='raw_out', type=str, - # help='Export raw data to file') + parser.add_argument('-a', dest='addr', + default=False, action='store_const', const=True, + help='Show address data with instructions') + parser.add_argument('-r', dest='raw', + default=False, action='store_const', const=True, + help='Show raw data with instructions') return parser.parse_args() def main(): @@ -219,9 +59,13 @@ def main(): exit(1) for idx in xrange(len(data)//16): inst = struct.unpack(b'<IIII', data[idx*16:idx*16+16]) - parsed = disassemble(isa, inst) + if args.addr: + out.write('%3x: ' % idx) + if args.raw: + out.write('%08x %08x %08x %08x ' % inst) warnings = [] - text = format_instruction(isa, parsed, warnings) + parsed = disassemble(isa, inst, warnings) + text = format_instruction(isa, parsed) out.write(text) if warnings: out.write(' ; ') |