def extract_procedures(code_file):
    result = {}
    procedure_pc, procedure, in_procedure = 0, [], 0
    while True:
        opcode_str = code_file.read(4)
        if len(opcode_str) != 4:
            break
        # >L is for big-endian files. Use <L for little-endian files.
        opcode = struct.unpack('>L', opcode_str)[0]
        if in_procedure:
            pc = code_file.tell() - 4
            op = mips.disassemble(pc, opcode)
            if isinstance(op, mips.JR) and op.s == 31:
                # JR $31 = return from procedure. We're about to finish!
                # We just need to get the delay slot, so 1 instruction is
                # left.
                procedure.append(op)
                in_procedure = 1
            elif len(procedure) > 16384 or isinstance(op, mips.Unknown):
                # We are probably parsing data that happened to look like
                # a procedure. Just ignore it.
                procedure, in_procedure = [], 0
            elif in_procedure == 1:
                # We've got the delay slot of the JR $31. We're finished!
                procedure.append(op)
                result[procedure_pc] = procedure
                procedure, in_procedure = [], 0
            else:
                procedure.append(op)
        else:
            # This checks for 'ADDIU $29, $29, <negative 4-byte-aligned>'.
            # That's a stack adjustment. Until now we haven't parsed
            # opcodes because we were probably in data, but we now need to
            # parse them, as a procedure is starting!
            if opcode & 0xFFFF8003 == 0x27BD8000:
                procedure_pc = pc = code_file.tell() - 4
                op = mips.disassemble(pc, opcode)
                procedure, in_procedure = [op], 2
    return result
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

import sys, mips

def simplify_notice(string):
    print "Simplification in %s" % (string)

mips.simplify_notice = simplify_notice

if __name__ == '__main__':
    for line in sys.stdin:
        if line.startswith('BLOCK '):
            print "-- Trace --"

            colon_tokens = [token.strip() for token in line[6:].split(':')]
            pc = int(colon_tokens[0], 16)
            mips_opcodes = [int(op_str, 16) for op_str in colon_tokens[1].split(' ')]
            mips_ops = [mips.disassemble(pc + n * 4, mips_opcode) for n, mips_opcode in enumerate(mips_opcodes)]

            int_state = mips.IntState()
            for n in xrange(len(mips_ops)):
                mips_op = mips_ops[n].simplify()
                print mips_op.as_string()
                mips_ops[n] = simplified_op = mips_op.update_int_state(int_state)
                if simplified_op is not mips_op:
                    print "%s= %s" % (" " * 8, simplified_op.as_string(pc=False))
 endian = '>L'  # >L is for big-endian files, <L for little-endian files.
 if len(sys.argv) >= 3:
     if sys.argv[2] == 'little':
         endian = '<L'
 procedure, procedure_pc, in_procedure = [], 0, 0
 with open(sys.argv[1], 'rb') as code_file:
     procedure_pc, procedure, in_procedure = 0, [], 0
     while True:
         opcode_str = code_file.read(4)
         if len(opcode_str) != 4:
             break
         # >L is for big-endian files. Use <L for little-endian files.
         opcode = struct.unpack(endian, opcode_str)[0]
         if in_procedure:
             pc = code_file.tell() - 4
             op = mips.disassemble(pc, opcode)
             if isinstance(op, mips.JR) and op.s == 31:
                 # JR $31 = return from procedure. We're about to finish!
                 # We just need to get the delay slot, so 1 instruction is
                 # left.
                 procedure.append(op)
                 in_procedure = 1
             elif len(procedure) > 16384 or isinstance(op, mips.Unknown):
                 # We are probably parsing data that happened to look like
                 # a procedure. Just ignore it.
                 procedure, in_procedure = [], 0
             elif in_procedure == 1:
                 # We've got the delay slot of the JR $31. We're finished!
                 procedure.append(op)
                 is_boundary = get_block_boundaries(procedure)
                 procedure = optimize(procedure, is_boundary)