class Error(Exception):
    def __init__(self, reason):
        super().__init__(reason)
        self.reason = reason

    def verbalize(self, program_name=None):
        def g():
            if program_name is not None:
                yield '%s: ' % program_name

            yield self.reason

        return ''.join(g()) class ADD(Instr):
    pass class ADC(Instr):
    pass class AND(Instr):
    pass class CP(Instr):
    pass class OR(Instr):
    pass class SBC(Instr):
    pass class SUB(Instr):
    pass class XOR(Instr):
    pass class BIT(Instr):
    pass class CALL(CallInstr):
    pass class CCF(Instr):
    pass class CPL(Instr):
    pass class DAA(Instr):
    pass class DEC(Instr):
    pass class DI(Instr):
    pass class DJNZ(JumpInstr):
    pass class EI(Instr):
    pass class EX(Instr):
    pass class EXX(Instr):
    pass class HALT(Instr):
    pass class IM(Instr):
    pass class INC(Instr):
    pass class IN(Instr):
    pass class JP(JumpInstr):
    pass class JR(JumpInstr):
    pass class LD(Instr):
    pass class LDDR(Instr):
    pass class LDIR(Instr):
    pass class NEG(Instr):
    pass class NOP(Instr):
    pass class RLC(Instr):
    pass class RL(Instr):
    pass class RR(Instr):
    pass class RRC(Instr):
    pass class SLA(Instr):
    pass class SRA(Instr):
    pass class SRL(Instr):
    pass class OUT(Instr):
    pass class POP(Instr):
    pass class PUSH(Instr):
    pass class RES(Instr):
    pass class RET(RetInstr):
    pass class RLA(Instr):
    pass class RLCA(Instr):
    pass class RLD(Instr):
    pass class RRA(Instr):
    pass class RRCA(Instr):
    pass class RST(CallInstr):
    pass class SCF(Instr):
    pass class SET(Instr):
    pass class A(metaclass=Reg):
    pass class AF(metaclass=Reg):
    pass class AF2(metaclass=Reg):
    pass class CF(metaclass=CondFlag):
    pass class M(metaclass=CondFlag):
    pass class NC(metaclass=CondFlag):
    pass class NZ(metaclass=CondFlag):
    pass class PO(metaclass=CondFlag):
    pass class P(metaclass=CondFlag):
    pass class Z(metaclass=CondFlag):
    pass class DE(metaclass=Reg):
    pass class BC(metaclass=Reg):
    pass class HL(metaclass=Reg):
    pass class IReg(metaclass=Reg):
    pass class IY(metaclass=IndexReg):
    pass class IX(metaclass=IndexReg):
    pass class SP(metaclass=Reg):
    pass class B(metaclass=Reg):
    pass class C(metaclass=Reg):
    pass class D(metaclass=Reg):
    pass class E(metaclass=Reg):
    pass class H(metaclass=Reg):
    pass class L(metaclass=Reg):
    pass class UnknownInstr(Instr):
    def __init__(self, addr, opcode):
        super().__init__()
        self.addr = addr
        self.size = 1
        self.opcode = opcode
        self.text = None

    def __str__(self):
        return 'db %#04x' % self.opcode class JumpInstr(Instr):
    @property
    def target(self):
        return self.ops[-1]

    @property
    def conditional(self):
        if isinstance(self, DJNZ):
            return True

        return len(self.ops) > 0 and isinstance(self.ops[0], CondFlag) class CallInstr(JumpInstr):
    pass class RetInstr(JumpInstr):
    pass class At(object):
    def __init__(self, op):
        self.ops = [op]

    def __repr__(self):
        return 'At(%r)' % tuple(self.ops)

    def __str__(self):
        op, = tuple(self.ops)
        return '(%s)' % _str_op(op) class IndexReg(Reg):
    pass class Add(object):
    def __init__(self, a, b):
        self.ops = [a, b]

    def __repr__(self):
        return 'Add(%r, %r)' % tuple(self.ops)

    def __str__(self):
        a, b = tuple(self.ops)

        sign = '+'
        if isinstance(b, int) and b < 0:
            sign = '-'
            b = -b

        return '%s %c %s' % (_str_op(a), sign, _str_op(b)) class Z80Machine(_MachineBase, _Z80Machine, Z80State):
    def __init__(self):
        Z80State.__init__(self, self.get_state_view())
import collections
import os
import tempfile
from ._error import Error
from ._instr import (ADD, ADC, AND, CP, OR, SBC, SUB, XOR, BIT, CALL, CCF, CPL,
                     DAA, DEC, DI, DJNZ, EI, EX, EXX, HALT, IM, INC, IN, JP,
                     JR, LD, LDDR, LDIR, NEG, NOP, RLC, RL, RR, RRC, SLA, SRA,
                     SRL, OUT, POP, PUSH, RES, RET, RLA, RLCA, RLD, RRA, RRCA,
                     RST, SCF, SET, A, AF, AF2, CF, M, NC, NZ, PO, P, Z, DE,
                     BC, HL, IReg, IY, IX, SP, B, C, D, E, H, L, UnknownInstr,
                     JumpInstr, CallInstr, RetInstr, At, IndexReg, Add)
from ._machine import Z80Machine
#   ivan@kosarev.info
#
#   Published under the MIT license.



class _DisasmError(Error):
    def __init__(self, subject, message, *notes):
        super().__init__('%s: %s: %s' % (subject.origin.inline_text,
                                         subject, message))
        self.subject = subject
        self.message = message
        self.notes = notes

    def verbalize(self, program_name=None):
        def g():
            yield self.subject.origin.context_text

            if program_name is not None:
                yield '%s: ' % program_name

            yield '%s' % self.reason

            for n in self.notes:
                yield '\n'
                yield n.verbalize()

        return ''.join(g())


class _Tag(object):
    def __init__(self, origin, addr, size):
        self.origin = origin
        self.addr = addr
        self.size = size
        self.comment = None

    def __str__(self):
        return '%s tag' % self.ID

    def __repr__(self):
        return '(%#06x, %s, %r)' % (self.addr, self.ID, self.comment)


class _CommentTag(_Tag):
    ID = 'comment'

    def __init__(self, origin, addr, comment):
        super().__init__(origin, addr, size=0)
        self.comment = comment


class _InlineCommentTag(_Tag):
    ID = 'inline_comment'

    def __init__(self, origin, addr, comment):
        super().__init__(origin, addr, size=0)
        self.comment = comment


class _HintTag(_Tag):
    ID = 'hint'

    def __init__(self, origin, addr, hint):
        super().__init__(origin, addr, size=0)
        self.comment = hint


class _ByteTag(_Tag):
    ID = 'byte'

    def __init__(self, origin, addr, value):
        super().__init__(origin, addr, size=1)
        self.value = value

    def __repr__(self):
        return '(%#06x, %s, %#04x, %r)' % (
            self.addr, self.ID, self.value, self.comment)


class _IncludeBinaryTag(_Tag):
    ID = 'include_binary'

    def __init__(self, origin, addr, filename, image):
        super().__init__(origin, addr, size=len(image))
        self.filename = filename
        self.image = image

    def __repr__(self):
        return '(%#06x, %s, %s, %s)' % (
            self.addr, self.ID, self.filename, self.comment)


class _InstrTag(_Tag):
    ID = 'instr'

    def __init__(self, origin, addr):
        super().__init__(origin, addr, size=0)


class _DisasmTag(_Tag):
    ID = 'disasm'

    def __init__(self, origin, addr):
        super().__init__(origin, addr, size=0)


class _UnknownInstrError(Exception):
    pass


class _Z80InstrBuilder(object):
    __INSTRS = {
        'Aadd': ADD,
        'Aadc': ADC,
        'Aand': AND,
        'Acp': CP,
        'add': ADD,
        'adc': ADC,
        'Aor': OR,

        'Asbc': SBC,