]> sigrok.org Git - libsigrokdecode.git/commitdiff
z80: New decoder for disassembling Z80 CPU instructions.
authorDaniel Elstner <redacted>
Tue, 18 Feb 2014 21:03:45 +0000 (22:03 +0100)
committerDaniel Elstner <redacted>
Mon, 24 Feb 2014 21:00:12 +0000 (22:00 +0100)
decoders/z80/__init__.py [new file with mode: 0644]
decoders/z80/pd.py [new file with mode: 0644]
decoders/z80/tables.py [new file with mode: 0644]

diff --git a/decoders/z80/__init__.py b/decoders/z80/__init__.py
new file mode 100644 (file)
index 0000000..aaf7c76
--- /dev/null
@@ -0,0 +1,35 @@
+##
+## This file is part of the libsigrokdecode project.
+##
+## Copyright (C) 2014 Daniel Elstner <daniel.kitta@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+'''
+The Zilog Z80 is an 8-bit microprocessor compatible with the Intel 8080.
+
+In addition to the 8-bit data bus, this decoder requires the input signals
+/M1 (machine cycle), /RD (read) and /WR (write) to do its work. An explicit
+clock signal is not required. However, the Z80 CPU clock may be used as
+sampling clock, if applicable.
+
+Notes on the Z80 opcode format and descriptions of both documented and
+"undocumented" opcodes are available here:
+
+  http://www.z80.info/decoding.htm
+  http://clrhome.org/table/
+'''
+
+from .pd import Decoder
diff --git a/decoders/z80/pd.py b/decoders/z80/pd.py
new file mode 100644 (file)
index 0000000..2baa02a
--- /dev/null
@@ -0,0 +1,362 @@
+##
+## This file is part of the libsigrokdecode project.
+##
+## Copyright (C) 2014 Daniel Elstner <daniel.kitta@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+import sigrokdecode as srd
+from functools import reduce
+from .tables import instr_table_by_prefix
+
+class Ann:
+    ADDR, MEMRD, MEMWR, IORD, IOWR, INSTR, ROP, WOP, WARN = range(9)
+class Row:
+    ADDRBUS, DATABUS, INSTRUCTIONS, OPERANDS, WARNINGS = range(5)
+class Pin:
+    D0, D7 = 0, 7
+    M1, RD, WR, MREQ, IORQ = range(8, 13)
+    A0, A15 = 13, 28
+class Cycle:
+    NONE, MEMRD, MEMWR, IORD, IOWR, FETCH, INTACK = range(7)
+
+class OpState:
+    IDLE    = 'IDLE'    # no current instruction
+    PRE1    = 'PRE1'    # first prefix
+    PRE2    = 'PRE2'    # second prefix
+    PREDIS  = 'PREDIS'  # pre-opcode displacement
+    OPCODE  = 'OPCODE'  # opcode byte
+    POSTDIS = 'POSTDIS' # post-opcode displacement
+    IMM1    = 'IMM1'    # first byte of immediate
+    IMM2    = 'IMM2'    # second byte of immediate
+    ROP1    = 'ROP1'    # first byte of read operand
+    ROP2    = 'ROP2'    # second byte of read operand
+    WOP1    = 'WOP1'    # first byte of write operand
+    WOP2    = 'WOP2'    # second byte of write operand
+    RESTART = 'RESTART' # restart instruction decoding
+
+ann_data_cycle_map = {
+    Cycle.MEMRD:  Ann.MEMRD,
+    Cycle.MEMWR:  Ann.MEMWR,
+    Cycle.IORD:   Ann.IORD,
+    Cycle.IOWR:   Ann.IOWR,
+    Cycle.FETCH:  Ann.MEMRD,
+    Cycle.INTACK: Ann.IORD,
+}
+
+def reduce_bus(bus):
+    if 0xFF in bus:
+        return None # unassigned bus probes
+    else:
+        return reduce(lambda a, b: (a << 1) | b, reversed(bus))
+
+def signed_byte(byte):
+    return byte if byte < 128 else byte - 256
+
+class Decoder(srd.Decoder):
+    api_version = 1
+    id          = 'z80'
+    name        = 'Z80'
+    longname    = 'Zilog Z80 CPU'
+    desc        = 'Zilog Z80 microprocessor disassembly.'
+    license     = 'gplv2+'
+    inputs      = ['logic']
+    outputs     = ['z80']
+    probes = [
+        {'id': 'd0', 'name': 'D0',  'desc': 'Data bus line 0'},
+        {'id': 'd1', 'name': 'D1',  'desc': 'Data bus line 1'},
+        {'id': 'd2', 'name': 'D2',  'desc': 'Data bus line 2'},
+        {'id': 'd3', 'name': 'D3',  'desc': 'Data bus line 3'},
+        {'id': 'd4', 'name': 'D4',  'desc': 'Data bus line 4'},
+        {'id': 'd5', 'name': 'D5',  'desc': 'Data bus line 5'},
+        {'id': 'd6', 'name': 'D6',  'desc': 'Data bus line 6'},
+        {'id': 'd7', 'name': 'D7',  'desc': 'Data bus line 7'},
+        {'id': 'm1', 'name': '/M1', 'desc': 'Machine cycle 1'},
+        {'id': 'rd', 'name': '/RD', 'desc': 'Memory or I/O read'},
+        {'id': 'wr', 'name': '/WR', 'desc': 'Memory or I/O write'},
+    ]
+    optional_probes = [
+        {'id': 'mreq', 'name': '/MREQ', 'desc': 'Memory request'},
+        {'id': 'iorq', 'name': '/IORQ', 'desc': 'I/O request'},
+        {'id': 'a0',   'name': 'A0',    'desc': 'Address bus line 0'},
+        {'id': 'a1',   'name': 'A1',    'desc': 'Address bus line 1'},
+        {'id': 'a2',   'name': 'A2',    'desc': 'Address bus line 2'},
+        {'id': 'a3',   'name': 'A3',    'desc': 'Address bus line 3'},
+        {'id': 'a4',   'name': 'A4',    'desc': 'Address bus line 4'},
+        {'id': 'a5',   'name': 'A5',    'desc': 'Address bus line 5'},
+        {'id': 'a6',   'name': 'A6',    'desc': 'Address bus line 6'},
+        {'id': 'a7',   'name': 'A7',    'desc': 'Address bus line 7'},
+        {'id': 'a8',   'name': 'A8',    'desc': 'Address bus line 8'},
+        {'id': 'a9',   'name': 'A9',    'desc': 'Address bus line 9'},
+        {'id': 'a10',  'name': 'A10',   'desc': 'Address bus line 10'},
+        {'id': 'a11',  'name': 'A11',   'desc': 'Address bus line 11'},
+        {'id': 'a12',  'name': 'A12',   'desc': 'Address bus line 12'},
+        {'id': 'a13',  'name': 'A13',   'desc': 'Address bus line 13'},
+        {'id': 'a14',  'name': 'A14',   'desc': 'Address bus line 14'},
+        {'id': 'a15',  'name': 'A15',   'desc': 'Address bus line 15'},
+    ]
+    options = {}
+    annotations = [
+        ['addr',    'Memory or I/O address'],
+        ['memrd',   'Byte read from memory'],
+        ['memwr',   'Byte written to memory'],
+        ['iord',    'Byte read from I/O port'],
+        ['iowr',    'Byte written to I/O port'],
+        ['instr',   'Z80 CPU instruction'],
+        ['rop',     'Value of input operand'],
+        ['wop',     'Value of output operand'],
+        ['warning', 'Warning message'],
+    ]
+    annotation_rows = (
+        ('addrbus', 'Address bus', (Ann.ADDR,)),
+        ('databus', 'Data bus', (Ann.MEMRD, Ann.MEMWR, Ann.IORD, Ann.IOWR)),
+        ('instructions', 'Instructions', (Ann.INSTR,)),
+        ('operands', 'Operands', (Ann.ROP, Ann.WOP)),
+        ('warnings', 'Warnings', (Ann.WARN,))
+    )
+
+    def __init__(self, **kwargs):
+        self.prev_cycle = Cycle.NONE
+        self.op_state   = OpState.IDLE
+
+    def start(self):
+        self.out_ann    = self.register(srd.OUTPUT_ANN)
+        self.bus_data   = None
+        self.samplenum  = None
+        self.addr_start = None
+        self.data_start = None
+        self.dasm_start = None
+        self.pend_addr  = None
+        self.pend_data  = None
+        self.ann_data   = None
+        self.ann_dasm   = None
+        self.prev_cycle = Cycle.NONE
+        self.op_state   = OpState.IDLE
+
+    def decode(self, ss, es, data):
+        for (self.samplenum, pins) in data:
+            cycle = Cycle.NONE
+            if pins[Pin.MREQ] != 1: # default to asserted
+                if pins[Pin.RD] == 0:
+                    cycle = Cycle.FETCH if pins[Pin.M1] == 0 else Cycle.MEMRD
+                elif pins[Pin.WR] == 0:
+                    cycle = Cycle.MEMWR
+            elif pins[Pin.IORQ] == 0: # default to not asserted
+                if pins[Pin.M1] == 0:
+                    cycle = Cycle.INTACK
+                elif pins[Pin.RD] == 0:
+                    cycle = Cycle.IORD
+                elif pins[Pin.WR] == 0:
+                    cycle = Cycle.IOWR
+
+            if cycle != Cycle.NONE:
+                self.bus_data = reduce_bus(pins[Pin.D0:Pin.D7+1])
+            if cycle != self.prev_cycle:
+                if self.prev_cycle == Cycle.NONE:
+                    self.on_cycle_begin(reduce_bus(pins[Pin.A0:Pin.A15+1]))
+                elif cycle == Cycle.NONE:
+                    self.on_cycle_end()
+                else:
+                    self.on_cycle_trans()
+            self.prev_cycle = cycle
+
+    def on_cycle_begin(self, bus_addr):
+        if self.pend_addr is not None:
+            self.put_text(self.addr_start, Ann.ADDR,
+                          '{:04X}'.format(self.pend_addr))
+        self.addr_start = self.samplenum
+        self.pend_addr  = bus_addr
+
+    def on_cycle_end(self):
+        self.op_state = getattr(self, 'on_state_' + self.op_state)()
+        if self.ann_dasm is not None:
+            self.put_disasm()
+        if self.op_state == OpState.RESTART:
+            self.op_state = self.on_state_IDLE()
+
+        if self.ann_data is not None:
+            self.put_text(self.data_start, self.ann_data,
+                          '{:02X}'.format(self.pend_data))
+        self.data_start = self.samplenum
+        self.pend_data  = self.bus_data
+        self.ann_data   = ann_data_cycle_map[self.prev_cycle]
+
+    def on_cycle_trans(self):
+        self.put_text(self.samplenum - 1, Ann.WARN,
+                      'Illegal transition between control states')
+        self.pend_addr = None
+        self.ann_data  = None
+        self.ann_dasm  = None
+
+    def put_disasm(self):
+        text = self.mnemonic.format(r=self.arg_reg, d=self.arg_dis,
+                                    i=self.arg_imm, ro=self.arg_read,
+                                    wo=self.arg_write)
+        self.put_text(self.dasm_start, self.ann_dasm, text)
+        self.ann_dasm   = None
+        self.dasm_start = self.samplenum
+
+    def put_text(self, ss, ann_idx, ann_text):
+        self.put(ss, self.samplenum, self.out_ann, [ann_idx, [ann_text]])
+
+    def on_state_IDLE(self):
+        if self.prev_cycle != Cycle.FETCH:
+            return OpState.IDLE
+        self.want_dis   = 0
+        self.want_imm   = 0
+        self.want_read  = 0
+        self.want_write = 0
+        self.want_wr_be = False
+        self.op_repeat  = False
+        self.arg_dis    = 0
+        self.arg_imm    = 0
+        self.arg_read   = 0
+        self.arg_write  = 0
+        self.arg_reg    = ''
+        self.mnemonic   = ''
+        self.instr_pend = False
+        self.read_pend  = False
+        self.write_pend = False
+        self.dasm_start = self.samplenum
+        self.op_prefix  = 0
+        if self.bus_data in (0xCB, 0xED, 0xDD, 0xFD):
+            return OpState.PRE1
+        else:
+            return OpState.OPCODE
+
+    def on_state_PRE1(self):
+        if self.prev_cycle != Cycle.FETCH:
+            self.mnemonic = 'Prefix not followed by fetch'
+            self.ann_dasm = Ann.WARN
+            return OpState.RESTART
+        self.op_prefix = self.pend_data
+        if self.op_prefix in (0xDD, 0xFD):
+            if self.bus_data == 0xCB:
+                return OpState.PRE2
+            if self.bus_data in (0xDD, 0xED, 0xFD):
+                return OpState.PRE1
+        return OpState.OPCODE
+
+    def on_state_PRE2(self):
+        if self.prev_cycle != Cycle.MEMRD:
+            self.mnemonic = 'Missing displacement'
+            self.ann_dasm = Ann.WARN
+            return OpState.RESTART
+        self.op_prefix = (self.op_prefix << 8) | self.pend_data
+        return OpState.PREDIS
+
+    def on_state_PREDIS(self):
+        if self.prev_cycle != Cycle.MEMRD:
+            self.mnemonic = 'Missing opcode'
+            self.ann_dasm = Ann.WARN
+            return OpState.RESTART
+        self.arg_dis = signed_byte(self.pend_data)
+        return OpState.OPCODE
+
+    def on_state_OPCODE(self):
+        (table, self.arg_reg) = instr_table_by_prefix[self.op_prefix]
+        self.op_prefix = 0
+        instruction = table.get(self.pend_data, None)
+        if instruction is None:
+            self.mnemonic = 'Invalid instruction'
+            self.ann_dasm = Ann.WARN
+            return OpState.RESTART
+        (self.want_dis, self.want_imm, self.want_read, want_write,
+                self.op_repeat, self.mnemonic) = instruction
+        self.want_write = abs(want_write)
+        self.want_wr_be = (want_write < 0)
+        if self.want_dis > 0:
+            return OpState.POSTDIS
+        if self.want_imm > 0:
+            return OpState.IMM1
+        self.ann_dasm = Ann.INSTR
+        if self.want_read > 0 and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
+            return OpState.ROP1
+        if self.want_write > 0 and self.prev_cycle in (Cycle.MEMWR, Cycle.IOWR):
+            return OpState.WOP1
+        return OpState.RESTART
+
+    def on_state_POSTDIS(self):
+        self.arg_dis = signed_byte(self.pend_data)
+        if self.want_imm > 0:
+            return OpState.IMM1
+        self.ann_dasm = Ann.INSTR
+        if self.want_read > 0:
+            return OpState.ROP1
+        if self.want_write > 0:
+            return OpState.WOP1
+        return OpState.RESTART
+
+    def on_state_IMM1(self):
+        self.arg_imm = self.pend_data
+        if self.want_imm > 1:
+            return OpState.IMM2
+        self.ann_dasm = Ann.INSTR
+        if self.want_read > 0:
+            return OpState.ROP1
+        if self.want_write > 0:
+            return OpState.WOP1
+        return OpState.RESTART
+
+    def on_state_IMM2(self):
+        self.arg_imm |= self.pend_data << 8
+        self.ann_dasm = Ann.INSTR
+        if self.want_read > 0:
+            return OpState.ROP1
+        if self.want_write > 0:
+            return OpState.WOP1
+        return OpState.RESTART
+
+    def on_state_ROP1(self):
+        self.arg_read = self.pend_data
+        if self.want_write > 0:
+            return OpState.WOP1
+        if self.want_read > 1:
+            return OpState.ROP2
+        if self.op_repeat and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
+            return OpState.ROP1
+        self.mnemonic = '{ro:02X}'
+        self.ann_dasm = Ann.ROP
+        return OpState.RESTART
+
+    def on_state_ROP2(self):
+        self.arg_read |= self.pend_data << 8
+        self.mnemonic = '{ro:04X}'
+        self.ann_dasm = Ann.ROP
+        if self.want_write > 0:
+            return OpState.WOP1
+        return OpState.RESTART
+
+    def on_state_WOP1(self):
+        self.arg_write = self.pend_data
+        if self.want_read > 1:
+            return OpState.ROP2
+        if self.want_write > 1:
+            return OpState.WOP2
+        if self.want_read > 0 and self.op_repeat and \
+                self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
+            return OpState.ROP1
+        self.mnemonic = '{wo:02X}'
+        self.ann_dasm = Ann.WOP
+        return OpState.RESTART
+
+    def on_state_WOP2(self):
+        if self.want_wr_be:
+            self.arg_write = (self.arg_write << 8) | self.pend_data
+        else:
+            self.arg_write |= self.pend_data << 8
+        self.mnemonic = '{wo:04X}'
+        self.ann_dasm = Ann.WOP
+        return OpState.RESTART
diff --git a/decoders/z80/tables.py b/decoders/z80/tables.py
new file mode 100644 (file)
index 0000000..b0d9e52
--- /dev/null
@@ -0,0 +1,1081 @@
+##
+## This file is part of the libsigrokdecode project.
+##
+## Copyright (C) 2014 Daniel Elstner <daniel.kitta@gmail.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+'''
+Instruction tuple: (d, i, ro, wo, rep, format string)
+
+  The placeholders d and i are the number of bytes in the instruction
+  used for the displacement and the immediate operand, respectively. An
+  operand consisting of more than one byte is assembled in little endian
+  order.
+  The format string should refer to the {d} and {i} operands by name.
+  Displacements are interpreted as signed integers, whereas immediate
+  operands are always read as unsigned. The tables for instructions
+  operating on the IX/IY index registers additionally use {r} in the
+  format string as a placeholder for the register name.
+  The placeholders ro and wo are the number of bytes the instruction
+  is expected to read or write, respectively. These counts are used
+  for both memory and I/O access, but not for immediate operands.
+  A negative value indicates that the operand byte order is big endian
+  rather than the usual little endian.
+  The placeholder rep is a boolean used to mark repeating instructions.
+'''
+
+# Instructions without a prefix
+main_instructions = {
+    0x00: (0, 0, 0, 0, False, 'NOP'),
+    0x01: (0, 2, 0, 0, False, 'LD BC,{i:04X}h'),
+    0x02: (0, 0, 0, 1, False, 'LD (BC),A'),
+    0x03: (0, 0, 0, 0, False, 'INC BC'),
+    0x04: (0, 0, 0, 0, False, 'INC B'),
+    0x05: (0, 0, 0, 0, False, 'DEC B'),
+    0x06: (0, 1, 0, 0, False, 'LD B,{i:02X}h'),
+    0x07: (0, 0, 0, 0, False, 'RLCA'),
+    0x08: (0, 0, 0, 0, False, 'EX AF,AF\''),
+    0x09: (0, 0, 0, 0, False, 'ADD HL,BC'),
+    0x0A: (0, 0, 1, 0, False, 'LD A,(BC)'),
+    0x0B: (0, 0, 0, 0, False, 'DEC BC'),
+    0x0C: (0, 0, 0, 0, False, 'INC C'),
+    0x0D: (0, 0, 0, 0, False, 'DEC C'),
+    0x0E: (0, 1, 0, 0, False, 'LD C,{i:02X}h'),
+    0x0F: (0, 0, 0, 0, False, 'RRCA'),
+
+    0x10: (1, 0, 0, 0, False, 'DJNZ {d:+d}'),
+    0x11: (0, 2, 0, 0, False, 'LD DE,{i:04X}h'),
+    0x12: (0, 0, 0, 1, False, 'LD (DE),A'),
+    0x13: (0, 0, 0, 0, False, 'INC DE'),
+    0x14: (0, 0, 0, 0, False, 'INC D'),
+    0x15: (0, 0, 0, 0, False, 'DEC D'),
+    0x16: (0, 1, 0, 0, False, 'LD D,{i:02X}h'),
+    0x17: (0, 0, 0, 0, False, 'RLA'),
+    0x18: (1, 0, 0, 0, False, 'JR {d:+d}'),
+    0x19: (0, 0, 0, 0, False, 'ADD HL,DE'),
+    0x1A: (0, 0, 1, 0, False, 'LD A,(DE)'),
+    0x1B: (0, 0, 0, 0, False, 'DEC DE'),
+    0x1C: (0, 0, 0, 0, False, 'INC E'),
+    0x1D: (0, 0, 0, 0, False, 'DEC E'),
+    0x1E: (0, 1, 0, 0, False, 'LD E,{i:02X}h'),
+    0x1F: (0, 0, 0, 0, False, 'RRA'),
+
+    0x20: (1, 0, 0, 0, False, 'JR NZ,{d:+d}'),
+    0x21: (0, 2, 0, 0, False, 'LD HL,{i:04X}h'),
+    0x22: (0, 2, 0, 2, False, 'LD ({i:04X}h),HL'),
+    0x23: (0, 0, 0, 0, False, 'INC HL'),
+    0x24: (0, 0, 0, 0, False, 'INC H'),
+    0x25: (0, 0, 0, 0, False, 'DEC H'),
+    0x26: (0, 1, 0, 0, False, 'LD H,{i:02X}h'),
+    0x27: (0, 0, 0, 0, False, 'DAA'),
+    0x28: (1, 0, 0, 0, False, 'JR Z,{d:+d}'),
+    0x29: (0, 0, 0, 0, False, 'ADD HL,HL'),
+    0x2A: (0, 2, 2, 0, False, 'LD HL,({i:04X}h)'),
+    0x2B: (0, 0, 0, 0, False, 'DEC HL'),
+    0x2C: (0, 0, 0, 0, False, 'INC L'),
+    0x2D: (0, 0, 0, 0, False, 'DEC L'),
+    0x2E: (0, 1, 0, 0, False, 'LD L,{i:02X}h'),
+    0x2F: (0, 0, 0, 0, False, 'CPL'),
+
+    0x30: (1, 0, 0, 0, False, 'JR NC,{d:+d}'),
+    0x31: (0, 2, 0, 0, False, 'LD SP,{i:04X}h'),
+    0x32: (0, 2, 0, 1, False, 'LD ({i:04X}h),A'),
+    0x33: (0, 0, 0, 0, False, 'INC SP'),
+    0x34: (0, 0, 1, 1, False, 'INC (HL)'),
+    0x35: (0, 0, 1, 1, False, 'DEC (HL)'),
+    0x36: (0, 1, 0, 1, False, 'LD (HL),{i:02X}h'),
+    0x37: (0, 0, 0, 0, False, 'SCF'),
+    0x38: (1, 0, 0, 0, False, 'JR C,{d:+d}'),
+    0x39: (0, 0, 0, 0, False, 'ADD HL,SP'),
+    0x3A: (0, 2, 1, 0, False, 'LD A,({i:04X}h)'),
+    0x3B: (0, 0, 0, 0, False, 'DEC SP'),
+    0x3C: (0, 0, 0, 0, False, 'INC A'),
+    0x3D: (0, 0, 0, 0, False, 'DEC A'),
+    0x3E: (0, 1, 0, 0, False, 'LD A,{i:02X}h'),
+    0x3F: (0, 0, 0, 0, False, 'CCF'),
+
+    0x40: (0, 0, 0, 0, False, 'LD B,B'),
+    0x41: (0, 0, 0, 0, False, 'LD B,C'),
+    0x42: (0, 0, 0, 0, False, 'LD B,D'),
+    0x43: (0, 0, 0, 0, False, 'LD B,E'),
+    0x44: (0, 0, 0, 0, False, 'LD B,H'),
+    0x45: (0, 0, 0, 0, False, 'LD B,L'),
+    0x46: (0, 0, 1, 0, False, 'LD B,(HL)'),
+    0x47: (0, 0, 0, 0, False, 'LD B,A'),
+    0x48: (0, 0, 0, 0, False, 'LD C,B'),
+    0x49: (0, 0, 0, 0, False, 'LD C,C'),
+    0x4A: (0, 0, 0, 0, False, 'LD C,D'),
+    0x4B: (0, 0, 0, 0, False, 'LD C,E'),
+    0x4C: (0, 0, 0, 0, False, 'LD C,H'),
+    0x4D: (0, 0, 0, 0, False, 'LD C,L'),
+    0x4E: (0, 0, 1, 0, False, 'LD C,(HL)'),
+    0x4F: (0, 0, 0, 0, False, 'LD C,A'),
+
+    0x50: (0, 0, 0, 0, False, 'LD D,B'),
+    0x51: (0, 0, 0, 0, False, 'LD D,C'),
+    0x52: (0, 0, 0, 0, False, 'LD D,D'),
+    0x53: (0, 0, 0, 0, False, 'LD D,E'),
+    0x54: (0, 0, 0, 0, False, 'LD D,H'),
+    0x55: (0, 0, 0, 0, False, 'LD D,L'),
+    0x56: (0, 0, 1, 0, False, 'LD D,(HL)'),
+    0x57: (0, 0, 0, 0, False, 'LD D,A'),
+    0x58: (0, 0, 0, 0, False, 'LD E,B'),
+    0x59: (0, 0, 0, 0, False, 'LD E,C'),
+    0x5A: (0, 0, 0, 0, False, 'LD E,D'),
+    0x5B: (0, 0, 0, 0, False, 'LD E,E'),
+    0x5C: (0, 0, 0, 0, False, 'LD E,H'),
+    0x5D: (0, 0, 0, 0, False, 'LD E,L'),
+    0x5E: (0, 0, 1, 0, False, 'LD E,(HL)'),
+    0x5F: (0, 0, 0, 0, False, 'LD E,A'),
+
+    0x60: (0, 0, 0, 0, False, 'LD H,B'),
+    0x61: (0, 0, 0, 0, False, 'LD H,C'),
+    0x62: (0, 0, 0, 0, False, 'LD H,D'),
+    0x63: (0, 0, 0, 0, False, 'LD H,E'),
+    0x64: (0, 0, 0, 0, False, 'LD H,H'),
+    0x65: (0, 0, 0, 0, False, 'LD H,L'),
+    0x66: (0, 0, 1, 0, False, 'LD H,(HL)'),
+    0x67: (0, 0, 0, 0, False, 'LD H,A'),
+    0x68: (0, 0, 0, 0, False, 'LD L,B'),
+    0x69: (0, 0, 0, 0, False, 'LD L,C'),
+    0x6A: (0, 0, 0, 0, False, 'LD L,D'),
+    0x6B: (0, 0, 0, 0, False, 'LD L,E'),
+    0x6C: (0, 0, 0, 0, False, 'LD L,H'),
+    0x6D: (0, 0, 0, 0, False, 'LD L,L'),
+    0x6E: (0, 0, 1, 0, False, 'LD L,(HL)'),
+    0x6F: (0, 0, 0, 0, False, 'LD L,A'),
+
+    0x70: (0, 0, 0, 1, False, 'LD (HL),B'),
+    0x71: (0, 0, 0, 1, False, 'LD (HL),C'),
+    0x72: (0, 0, 0, 1, False, 'LD (HL),D'),
+    0x73: (0, 0, 0, 1, False, 'LD (HL),E'),
+    0x74: (0, 0, 0, 1, False, 'LD (HL),H'),
+    0x75: (0, 0, 0, 1, False, 'LD (HL),L'),
+    0x76: (0, 0, 0, 0, False, 'HALT'),
+    0x77: (0, 0, 0, 1, False, 'LD (HL),A'),
+    0x78: (0, 0, 0, 0, False, 'LD A,B'),
+    0x79: (0, 0, 0, 0, False, 'LD A,C'),
+    0x7A: (0, 0, 0, 0, False, 'LD A,D'),
+    0x7B: (0, 0, 0, 0, False, 'LD A,E'),
+    0x7C: (0, 0, 0, 0, False, 'LD A,H'),
+    0x7D: (0, 0, 0, 0, False, 'LD A,L'),
+    0x7E: (0, 0, 1, 0, False, 'LD A,(HL)'),
+    0x7F: (0, 0, 0, 0, False, 'LD A,A'),
+
+    0x80: (0, 0, 0, 0, False, 'ADD A,B'),
+    0x81: (0, 0, 0, 0, False, 'ADD A,C'),
+    0x82: (0, 0, 0, 0, False, 'ADD A,D'),
+    0x83: (0, 0, 0, 0, False, 'ADD A,E'),
+    0x84: (0, 0, 0, 0, False, 'ADD A,H'),
+    0x85: (0, 0, 0, 0, False, 'ADD A,L'),
+    0x86: (0, 0, 1, 0, False, 'ADD A,(HL)'),
+    0x87: (0, 0, 0, 0, False, 'ADD A,A'),
+    0x88: (0, 0, 0, 0, False, 'ADC A,B'),
+    0x89: (0, 0, 0, 0, False, 'ADC A,C'),
+    0x8A: (0, 0, 0, 0, False, 'ADC A,D'),
+    0x8B: (0, 0, 0, 0, False, 'ADC A,E'),
+    0x8C: (0, 0, 0, 0, False, 'ADC A,H'),
+    0x8D: (0, 0, 0, 0, False, 'ADC A,L'),
+    0x8E: (0, 0, 1, 0, False, 'ADC A,(HL)'),
+    0x8F: (0, 0, 0, 0, False, 'ADC A,A'),
+
+    0x90: (0, 0, 0, 0, False, 'SUB B'),
+    0x91: (0, 0, 0, 0, False, 'SUB C'),
+    0x92: (0, 0, 0, 0, False, 'SUB D'),
+    0x93: (0, 0, 0, 0, False, 'SUB E'),
+    0x94: (0, 0, 0, 0, False, 'SUB H'),
+    0x95: (0, 0, 0, 0, False, 'SUB L'),
+    0x96: (0, 0, 1, 0, False, 'SUB (HL)'),
+    0x97: (0, 0, 0, 0, False, 'SUB A'),
+    0x98: (0, 0, 0, 0, False, 'SBC A,B'),
+    0x99: (0, 0, 0, 0, False, 'SBC A,C'),
+    0x9A: (0, 0, 0, 0, False, 'SBC A,D'),
+    0x9B: (0, 0, 0, 0, False, 'SBC A,E'),
+    0x9C: (0, 0, 0, 0, False, 'SBC A,H'),
+    0x9D: (0, 0, 0, 0, False, 'SBC A,L'),
+    0x9E: (0, 0, 1, 0, False, 'SBC A,(HL)'),
+    0x9F: (0, 0, 0, 0, False, 'SBC A,A'),
+
+    0xA0: (0, 0, 0, 0, False, 'AND B'),
+    0xA1: (0, 0, 0, 0, False, 'AND C'),
+    0xA2: (0, 0, 0, 0, False, 'AND D'),
+    0xA3: (0, 0, 0, 0, False, 'AND E'),
+    0xA4: (0, 0, 0, 0, False, 'AND H'),
+    0xA5: (0, 0, 0, 0, False, 'AND L'),
+    0xA6: (0, 0, 1, 0, False, 'AND (HL)'),
+    0xA7: (0, 0, 0, 0, False, 'AND A'),
+    0xA8: (0, 0, 0, 0, False, 'XOR B'),
+    0xA9: (0, 0, 0, 0, False, 'XOR C'),
+    0xAA: (0, 0, 0, 0, False, 'XOR D'),
+    0xAB: (0, 0, 0, 0, False, 'XOR E'),
+    0xAC: (0, 0, 0, 0, False, 'XOR H'),
+    0xAD: (0, 0, 0, 0, False, 'XOR L'),
+    0xAE: (0, 0, 1, 0, False, 'XOR (HL)'),
+    0xAF: (0, 0, 0, 0, False, 'XOR A'),
+
+    0xB0: (0, 0, 0, 0, False, 'OR B'),
+    0xB1: (0, 0, 0, 0, False, 'OR C'),
+    0xB2: (0, 0, 0, 0, False, 'OR D'),
+    0xB3: (0, 0, 0, 0, False, 'OR E'),
+    0xB4: (0, 0, 0, 0, False, 'OR H'),
+    0xB5: (0, 0, 0, 0, False, 'OR L'),
+    0xB6: (0, 0, 1, 0, False, 'OR (HL)'),
+    0xB7: (0, 0, 0, 0, False, 'OR A'),
+    0xB8: (0, 0, 0, 0, False, 'CP B'),
+    0xB9: (0, 0, 0, 0, False, 'CP C'),
+    0xBA: (0, 0, 0, 0, False, 'CP D'),
+    0xBB: (0, 0, 0, 0, False, 'CP E'),
+    0xBC: (0, 0, 0, 0, False, 'CP H'),
+    0xBD: (0, 0, 0, 0, False, 'CP L'),
+    0xBE: (0, 0, 1, 0, False, 'CP (HL)'),
+    0xBF: (0, 0, 0, 0, False, 'CP A'),
+
+    0xC0: (0, 0, 2, 0, False, 'RET NZ'),
+    0xC1: (0, 0, 2, 0, False, 'POP BC'),
+    0xC2: (0, 2, 0, 0, False, 'JP NZ,{i:04X}h'),
+    0xC3: (0, 2, 0, 0, False, 'JP {i:04X}h'),
+    0xC4: (0, 2, 0,-2, False, 'CALL NZ,{i:04X}h'),
+    0xC5: (0, 0, 0,-2, False, 'PUSH BC'),
+    0xC6: (0, 1, 0, 0, False, 'ADD A,{i:02X}h'),
+    0xC7: (0, 0, 0,-2, False, 'RST 00h'),
+    0xC8: (0, 0, 2, 0, False, 'RET Z'),
+    0xC9: (0, 0, 2, 0, False, 'RET'),
+    0xCA: (0, 2, 0, 0, False, 'JP Z,{i:04X}h'),
+
+    0xCC: (0, 2, 0,-2, False, 'CALL Z,{i:04X}h'),
+    0xCD: (0, 2, 0,-2, False, 'CALL {i:04X}h'),
+    0xCE: (0, 1, 0, 0, False, 'ADC A,{i:02X}h'),
+    0xCF: (0, 0, 0,-2, False, 'RST 08h'),
+
+    0xD0: (0, 0, 2, 0, False, 'RET NC'),
+    0xD1: (0, 0, 2, 0, False, 'POP DE'),
+    0xD2: (0, 2, 0, 0, False, 'JP NC,{i:04X}h'),
+    0xD3: (0, 1, 0, 1, False, 'OUT ({i:02X}h),A'),
+    0xD4: (0, 2, 0,-2, False, 'CALL NC,{i:04X}h'),
+    0xD5: (0, 0, 0,-2, False, 'PUSH DE'),
+    0xD6: (0, 1, 0, 0, False, 'SUB {i:02X}h'),
+    0xD7: (0, 0, 0,-2, False, 'RST 10h'),
+    0xD8: (0, 0, 2, 0, False, 'RET C'),
+    0xD9: (0, 0, 0, 0, False, 'EXX'),
+    0xDA: (0, 2, 0, 0, False, 'JP C,{i:04X}h'),
+    0xDB: (0, 1, 1, 0, False, 'IN A,({i:02X}h)'),
+    0xDC: (0, 2, 0,-2, False, 'CALL C,{i:04X}h'),
+
+    0xDE: (0, 1, 0, 0, False, 'SBC A,{i:02X}h'),
+    0xDF: (0, 0, 0,-2, False, 'RST 18h'),
+
+    0xE0: (0, 0, 2, 0, False, 'RET PO'),
+    0xE1: (0, 0, 2, 0, False, 'POP HL'),
+    0xE2: (0, 2, 0, 0, False, 'JP PO,{i:04X}h'),
+    0xE3: (0, 0, 2, 2, False, 'EX (SP),HL'),
+    0xE4: (0, 2, 0,-2, False, 'CALL PO,{i:04X}h'),
+    0xE5: (0, 0, 0,-2, False, 'PUSH HL'),
+    0xE6: (0, 1, 0, 0, False, 'AND {i:02X}h'),
+    0xE7: (0, 0, 0,-2, False, 'RST 20h'),
+    0xE8: (0, 0, 2, 0, False, 'RET PE'),
+    0xE9: (0, 0, 0, 0, False, 'JP (HL)'),
+    0xEA: (0, 2, 0, 0, False, 'JP PE,{i:04X}h'),
+    0xEB: (0, 0, 0, 0, False, 'EX DE,HL'),
+    0xEC: (0, 2, 0,-2, False, 'CALL PE,{i:04X}h'),
+
+    0xEE: (0, 1, 0, 0, False, 'XOR {i:02X}h'),
+    0xEF: (0, 0, 0,-2, False, 'RST 28h'),
+
+    0xF0: (0, 0, 2, 0, False, 'RET P'),
+    0xF1: (0, 0, 2, 0, False, 'POP AF'),
+    0xF2: (0, 2, 0, 0, False, 'JP P,{i:04X}h'),
+    0xF3: (0, 0, 0, 0, False, 'DI'),
+    0xF4: (0, 2, 0,-2, False, 'CALL P,{i:04X}h'),
+    0xF5: (0, 0, 0,-2, False, 'PUSH AF'),
+    0xF6: (0, 1, 0, 0, False, 'OR {i:02X}h'),
+    0xF7: (0, 0, 0,-2, False, 'RST 30h'),
+    0xF8: (0, 0, 2, 0, False, 'RET M'),
+    0xF9: (0, 0, 0, 0, False, 'LD SP,HL'),
+    0xFA: (0, 2, 0, 0, False, 'JP M,{i:04X}h'),
+    0xFB: (0, 0, 0, 0, False, 'EI'),
+    0xFC: (0, 2, 0,-2, False, 'CALL M,{i:04X}h'),
+
+    0xFE: (0, 1, 0, 0, False, 'CP {i:02X}h'),
+    0xFF: (0, 0, 0,-2, False, 'RST 38h')
+}
+
+# Instructions with ED prefix
+extended_instructions = {
+    0x40: (0, 0, 1, 0, False, 'IN B,(C)'),
+    0x41: (0, 0, 0, 1, False, 'OUT (C),B'),
+    0x42: (0, 0, 0, 0, False, 'SBC HL,BC'),
+    0x43: (0, 2, 0, 2, False, 'LD ({i:04X}h),BC'),
+    0x44: (0, 0, 0, 0, False, 'NEG'),
+    0x45: (0, 0, 2, 0, False, 'RETN'),
+    0x46: (0, 0, 0, 0, False, 'IM 0'),
+    0x47: (0, 0, 0, 0, False, 'LD I,A'),
+    0x48: (0, 0, 1, 0, False, 'IN C,(C)'),
+    0x49: (0, 0, 0, 1, False, 'OUT (C),C'),
+    0x4A: (0, 0, 0, 0, False, 'ADC HL,BC'),
+    0x4B: (0, 2, 2, 0, False, 'LD BC,({i:04X}h)'),
+    0x4C: (0, 0, 0, 0, False, 'NEG'),
+    0x4D: (0, 0, 2, 0, False, 'RETI'),
+    0x4E: (0, 0, 0, 0, False, 'IM 0/1'),
+    0x4F: (0, 0, 0, 0, False, 'LD R,A'),
+
+    0x50: (0, 0, 1, 0, False, 'IN D,(C)'),
+    0x51: (0, 0, 0, 1, False, 'OUT (C),D'),
+    0x52: (0, 0, 0, 0, False, 'SBC HL,DE'),
+    0x53: (0, 2, 0, 2, False, 'LD ({i:04X}h),DE'),
+    0x54: (0, 0, 0, 0, False, 'NEG'),
+    0x55: (0, 0, 2, 0, False, 'RETN'),
+    0x56: (0, 0, 0, 0, False, 'IM 1'),
+    0x57: (0, 0, 0, 0, False, 'LD A,I'),
+    0x58: (0, 0, 1, 0, False, 'IN E,(C)'),
+    0x59: (0, 0, 0, 1, False, 'OUT (C),E'),
+    0x5A: (0, 0, 0, 0, False, 'ADC HL,DE'),
+    0x5B: (0, 2, 2, 0, False, 'LD DE,({i:04X}h)'),
+    0x5C: (0, 0, 0, 0, False, 'NEG'),
+    0x5D: (0, 0, 2, 0, False, 'RETN'),
+    0x5E: (0, 0, 0, 0, False, 'IM 2'),
+    0x5F: (0, 0, 0, 0, False, 'LD A,R'),
+
+    0x60: (0, 0, 1, 0, False, 'IN H,(C)'),
+    0x61: (0, 0, 0, 1, False, 'OUT (C),H'),
+    0x62: (0, 0, 0, 0, False, 'SBC HL,HL'),
+    0x63: (0, 2, 0, 2, False, 'LD ({i:04X}h),HL'),
+    0x64: (0, 0, 0, 0, False, 'NEG'),
+    0x65: (0, 0, 2, 0, False, 'RETN'),
+    0x66: (0, 0, 0, 0, False, 'IM 0'),
+    0x67: (0, 0, 1, 1, False, 'RRD'),
+    0x68: (0, 0, 1, 0, False, 'IN L,(C)'),
+    0x69: (0, 0, 0, 1, False, 'OUT (C),L'),
+    0x6A: (0, 0, 0, 0, False, 'ADC HL,HL'),
+    0x6B: (0, 2, 2, 0, False, 'LD HL,({i:04X}h)'),
+    0x6C: (0, 0, 0, 0, False, 'NEG'),
+    0x6D: (0, 0, 2, 0, False, 'RETN'),
+    0x6E: (0, 0, 0, 0, False, 'IM 0/1'),
+    0x6F: (0, 0, 1, 1, False, 'RLD'),
+
+    0x70: (0, 0, 1, 0, False, 'IN (C)'),
+    0x71: (0, 0, 0, 1, False, 'OUT (C),0'),
+    0x72: (0, 0, 0, 0, False, 'SBC HL,SP'),
+    0x73: (0, 2, 0, 2, False, 'LD ({i:04X}h),SP'),
+    0x74: (0, 0, 0, 0, False, 'NEG'),
+    0x75: (0, 0, 2, 0, False, 'RETN'),
+    0x76: (0, 0, 0, 0, False, 'IM 1'),
+
+    0x78: (0, 0, 1, 0, False, 'IN A,(C)'),
+    0x79: (0, 0, 0, 1, False, 'OUT (C),A'),
+    0x7A: (0, 0, 0, 0, False, 'ADC HL,SP'),
+    0x7B: (0, 2, 2, 0, False, 'LD SP,({i:04X}h)'),
+    0x7C: (0, 0, 0, 0, False, 'NEG'),
+    0x7D: (0, 0, 2, 0, False, 'RETN'),
+    0x7E: (0, 0, 0, 0, False, 'IM 2'),
+
+    0xA0: (0, 0, 1, 1, False, 'LDI'),
+    0xA1: (0, 0, 1, 0, False, 'CPI'),
+    0xA2: (0, 0, 1, 1, False, 'INI'),
+    0xA3: (0, 0, 1, 1, False, 'OUTI'),
+
+    0xA8: (0, 0, 1, 1, False, 'LDD'),
+    0xA9: (0, 0, 1, 0, False, 'CPD'),
+    0xAA: (0, 0, 1, 1, False, 'IND'),
+    0xAB: (0, 0, 1, 1, False, 'OUTD'),
+
+    0xB0: (0, 0, 1, 1, True,  'LDIR'),
+    0xB1: (0, 0, 1, 0, True,  'CPIR'),
+    0xB2: (0, 0, 1, 1, True,  'INIR'),
+    0xB3: (0, 0, 1, 1, True,  'OTIR'),
+
+    0xB8: (0, 0, 1, 1, True,  'LDDR'),
+    0xB9: (0, 0, 1, 0, True,  'CPDR'),
+    0xBA: (0, 0, 1, 1, True,  'INDR'),
+    0xBB: (0, 0, 1, 1, True,  'OTDR')
+}
+
+# Instructions with CB prefix
+bit_instructions = {
+    0x00: (0, 0, 0, 0, False, 'RLC B'),
+    0x01: (0, 0, 0, 0, False, 'RLC C'),
+    0x02: (0, 0, 0, 0, False, 'RLC D'),
+    0x03: (0, 0, 0, 0, False, 'RLC E'),
+    0x04: (0, 0, 0, 0, False, 'RLC H'),
+    0x05: (0, 0, 0, 0, False, 'RLC L'),
+    0x06: (0, 0, 1, 1, False, 'RLC (HL)'),
+    0x07: (0, 0, 0, 0, False, 'RLC A'),
+    0x08: (0, 0, 0, 0, False, 'RRC B'),
+    0x09: (0, 0, 0, 0, False, 'RRC C'),
+    0x0A: (0, 0, 0, 0, False, 'RRC D'),
+    0x0B: (0, 0, 0, 0, False, 'RRC E'),
+    0x0C: (0, 0, 0, 0, False, 'RRC H'),
+    0x0D: (0, 0, 0, 0, False, 'RRC L'),
+    0x0E: (0, 0, 1, 1, False, 'RRC (HL)'),
+    0x0F: (0, 0, 0, 0, False, 'RRC A'),
+
+    0x10: (0, 0, 0, 0, False, 'RL B'),
+    0x11: (0, 0, 0, 0, False, 'RL C'),
+    0x12: (0, 0, 0, 0, False, 'RL D'),
+    0x13: (0, 0, 0, 0, False, 'RL E'),
+    0x14: (0, 0, 0, 0, False, 'RL H'),
+    0x15: (0, 0, 0, 0, False, 'RL L'),
+    0x16: (0, 0, 1, 1, False, 'RL (HL)'),
+    0x17: (0, 0, 0, 0, False, 'RL A'),
+    0x18: (0, 0, 0, 0, False, 'RR B'),
+    0x19: (0, 0, 0, 0, False, 'RR C'),
+    0x1A: (0, 0, 0, 0, False, 'RR D'),
+    0x1B: (0, 0, 0, 0, False, 'RR E'),
+    0x1C: (0, 0, 0, 0, False, 'RR H'),
+    0x1D: (0, 0, 0, 0, False, 'RR L'),
+    0x1E: (0, 0, 1, 1, False, 'RR (HL)'),
+    0x1F: (0, 0, 0, 0, False, 'RR A'),
+
+    0x20: (0, 0, 0, 0, False, 'SLA B'),
+    0x21: (0, 0, 0, 0, False, 'SLA C'),
+    0x22: (0, 0, 0, 0, False, 'SLA D'),
+    0x23: (0, 0, 0, 0, False, 'SLA E'),
+    0x24: (0, 0, 0, 0, False, 'SLA H'),
+    0x25: (0, 0, 0, 0, False, 'SLA L'),
+    0x26: (0, 0, 1, 1, False, 'SLA (HL)'),
+    0x27: (0, 0, 0, 0, False, 'SLA A'),
+    0x28: (0, 0, 0, 0, False, 'SRA B'),
+    0x29: (0, 0, 0, 0, False, 'SRA C'),
+    0x2A: (0, 0, 0, 0, False, 'SRA D'),
+    0x2B: (0, 0, 0, 0, False, 'SRA E'),
+    0x2C: (0, 0, 0, 0, False, 'SRA H'),
+    0x2D: (0, 0, 0, 0, False, 'SRA L'),
+    0x2E: (0, 0, 1, 1, False, 'SRA (HL)'),
+    0x2F: (0, 0, 0, 0, False, 'SRA A'),
+
+    0x30: (0, 0, 0, 0, False, 'SLL B'),
+    0x31: (0, 0, 0, 0, False, 'SLL C'),
+    0x32: (0, 0, 0, 0, False, 'SLL D'),
+    0x33: (0, 0, 0, 0, False, 'SLL E'),
+    0x34: (0, 0, 0, 0, False, 'SLL H'),
+    0x35: (0, 0, 0, 0, False, 'SLL L'),
+    0x36: (0, 0, 1, 1, False, 'SLL (HL)'),
+    0x37: (0, 0, 0, 0, False, 'SLL A'),
+    0x38: (0, 0, 0, 0, False, 'SRL B'),
+    0x39: (0, 0, 0, 0, False, 'SRL C'),
+    0x3A: (0, 0, 0, 0, False, 'SRL D'),
+    0x3B: (0, 0, 0, 0, False, 'SRL E'),
+    0x3C: (0, 0, 0, 0, False, 'SRL H'),
+    0x3D: (0, 0, 0, 0, False, 'SRL L'),
+    0x3E: (0, 0, 1, 1, False, 'SRL (HL)'),
+    0x3F: (0, 0, 0, 0, False, 'SRL A'),
+
+    0x40: (0, 0, 0, 0, False, 'BIT 0,B'),
+    0x41: (0, 0, 0, 0, False, 'BIT 0,C'),
+    0x42: (0, 0, 0, 0, False, 'BIT 0,D'),
+    0x43: (0, 0, 0, 0, False, 'BIT 0,E'),
+    0x44: (0, 0, 0, 0, False, 'BIT 0,H'),
+    0x45: (0, 0, 0, 0, False, 'BIT 0,L'),
+    0x46: (0, 0, 1, 0, False, 'BIT 0,(HL)'),
+    0x47: (0, 0, 0, 0, False, 'BIT 0,A'),
+    0x48: (0, 0, 0, 0, False, 'BIT 1,B'),
+    0x49: (0, 0, 0, 0, False, 'BIT 1,C'),
+    0x4A: (0, 0, 0, 0, False, 'BIT 1,D'),
+    0x4B: (0, 0, 0, 0, False, 'BIT 1,E'),
+    0x4C: (0, 0, 0, 0, False, 'BIT 1,H'),
+    0x4D: (0, 0, 0, 0, False, 'BIT 1,L'),
+    0x4E: (0, 0, 1, 0, False, 'BIT 1,(HL)'),
+    0x4F: (0, 0, 0, 0, False, 'BIT 1,A'),
+
+    0x50: (0, 0, 0, 0, False, 'BIT 2,B'),
+    0x51: (0, 0, 0, 0, False, 'BIT 2,C'),
+    0x52: (0, 0, 0, 0, False, 'BIT 2,D'),
+    0x53: (0, 0, 0, 0, False, 'BIT 2,E'),
+    0x54: (0, 0, 0, 0, False, 'BIT 2,H'),
+    0x55: (0, 0, 0, 0, False, 'BIT 2,L'),
+    0x56: (0, 0, 1, 0, False, 'BIT 2,(HL)'),
+    0x57: (0, 0, 0, 0, False, 'BIT 2,A'),
+    0x58: (0, 0, 0, 0, False, 'BIT 3,B'),
+    0x59: (0, 0, 0, 0, False, 'BIT 3,C'),
+    0x5A: (0, 0, 0, 0, False, 'BIT 3,D'),
+    0x5B: (0, 0, 0, 0, False, 'BIT 3,E'),
+    0x5C: (0, 0, 0, 0, False, 'BIT 3,H'),
+    0x5D: (0, 0, 0, 0, False, 'BIT 3,L'),
+    0x5E: (0, 0, 1, 0, False, 'BIT 3,(HL)'),
+    0x5F: (0, 0, 0, 0, False, 'BIT 3,A'),
+
+    0x60: (0, 0, 0, 0, False, 'BIT 4,B'),
+    0x61: (0, 0, 0, 0, False, 'BIT 4,C'),
+    0x62: (0, 0, 0, 0, False, 'BIT 4,D'),
+    0x63: (0, 0, 0, 0, False, 'BIT 4,E'),
+    0x64: (0, 0, 0, 0, False, 'BIT 4,H'),
+    0x65: (0, 0, 0, 0, False, 'BIT 4,L'),
+    0x66: (0, 0, 1, 0, False, 'BIT 4,(HL)'),
+    0x67: (0, 0, 0, 0, False, 'BIT 4,A'),
+    0x68: (0, 0, 0, 0, False, 'BIT 5,B'),
+    0x69: (0, 0, 0, 0, False, 'BIT 5,C'),
+    0x6A: (0, 0, 0, 0, False, 'BIT 5,D'),
+    0x6B: (0, 0, 0, 0, False, 'BIT 5,E'),
+    0x6C: (0, 0, 0, 0, False, 'BIT 5,H'),
+    0x6D: (0, 0, 0, 0, False, 'BIT 5,L'),
+    0x6E: (0, 0, 1, 0, False, 'BIT 5,(HL)'),
+    0x6F: (0, 0, 0, 0, False, 'BIT 5,A'),
+
+    0x70: (0, 0, 0, 0, False, 'BIT 6,B'),
+    0x71: (0, 0, 0, 0, False, 'BIT 6,C'),
+    0x72: (0, 0, 0, 0, False, 'BIT 6,D'),
+    0x73: (0, 0, 0, 0, False, 'BIT 6,E'),
+    0x74: (0, 0, 0, 0, False, 'BIT 6,H'),
+    0x75: (0, 0, 0, 0, False, 'BIT 6,L'),
+    0x76: (0, 0, 1, 0, False, 'BIT 6,(HL)'),
+    0x77: (0, 0, 0, 0, False, 'BIT 6,A'),
+    0x78: (0, 0, 0, 0, False, 'BIT 7,B'),
+    0x79: (0, 0, 0, 0, False, 'BIT 7,C'),
+    0x7A: (0, 0, 0, 0, False, 'BIT 7,D'),
+    0x7B: (0, 0, 0, 0, False, 'BIT 7,E'),
+    0x7C: (0, 0, 0, 0, False, 'BIT 7,H'),
+    0x7D: (0, 0, 0, 0, False, 'BIT 7,L'),
+    0x7E: (0, 0, 1, 0, False, 'BIT 7,(HL)'),
+    0x7F: (0, 0, 0, 0, False, 'BIT 7,A'),
+
+    0x80: (0, 0, 0, 0, False, 'RES 0,B'),
+    0x81: (0, 0, 0, 0, False, 'RES 0,C'),
+    0x82: (0, 0, 0, 0, False, 'RES 0,D'),
+    0x83: (0, 0, 0, 0, False, 'RES 0,E'),
+    0x84: (0, 0, 0, 0, False, 'RES 0,H'),
+    0x85: (0, 0, 0, 0, False, 'RES 0,L'),
+    0x86: (0, 0, 1, 1, False, 'RES 0,(HL)'),
+    0x87: (0, 0, 0, 0, False, 'RES 0,A'),
+    0x88: (0, 0, 0, 0, False, 'RES 1,B'),
+    0x89: (0, 0, 0, 0, False, 'RES 1,C'),
+    0x8A: (0, 0, 0, 0, False, 'RES 1,D'),
+    0x8B: (0, 0, 0, 0, False, 'RES 1,E'),
+    0x8C: (0, 0, 0, 0, False, 'RES 1,H'),
+    0x8D: (0, 0, 0, 0, False, 'RES 1,L'),
+    0x8E: (0, 0, 1, 1, False, 'RES 1,(HL)'),
+    0x8F: (0, 0, 0, 0, False, 'RES 1,A'),
+
+    0x90: (0, 0, 0, 0, False, 'RES 2,B'),
+    0x91: (0, 0, 0, 0, False, 'RES 2,C'),
+    0x92: (0, 0, 0, 0, False, 'RES 2,D'),
+    0x93: (0, 0, 0, 0, False, 'RES 2,E'),
+    0x94: (0, 0, 0, 0, False, 'RES 2,H'),
+    0x95: (0, 0, 0, 0, False, 'RES 2,L'),
+    0x96: (0, 0, 1, 1, False, 'RES 2,(HL)'),
+    0x97: (0, 0, 0, 0, False, 'RES 2,A'),
+    0x98: (0, 0, 0, 0, False, 'RES 3,B'),
+    0x99: (0, 0, 0, 0, False, 'RES 3,C'),
+    0x9A: (0, 0, 0, 0, False, 'RES 3,D'),
+    0x9B: (0, 0, 0, 0, False, 'RES 3,E'),
+    0x9C: (0, 0, 0, 0, False, 'RES 3,H'),
+    0x9D: (0, 0, 0, 0, False, 'RES 3,L'),
+    0x9E: (0, 0, 1, 1, False, 'RES 3,(HL)'),
+    0x9F: (0, 0, 0, 0, False, 'RES 3,A'),
+
+    0xA0: (0, 0, 0, 0, False, 'RES 4,B'),
+    0xA1: (0, 0, 0, 0, False, 'RES 4,C'),
+    0xA2: (0, 0, 0, 0, False, 'RES 4,D'),
+    0xA3: (0, 0, 0, 0, False, 'RES 4,E'),
+    0xA4: (0, 0, 0, 0, False, 'RES 4,H'),
+    0xA5: (0, 0, 0, 0, False, 'RES 4,L'),
+    0xA6: (0, 0, 1, 1, False, 'RES 4,(HL)'),
+    0xA7: (0, 0, 0, 0, False, 'RES 4,A'),
+    0xA8: (0, 0, 0, 0, False, 'RES 5,B'),
+    0xA9: (0, 0, 0, 0, False, 'RES 5,C'),
+    0xAA: (0, 0, 0, 0, False, 'RES 5,D'),
+    0xAB: (0, 0, 0, 0, False, 'RES 5,E'),
+    0xAC: (0, 0, 0, 0, False, 'RES 5,H'),
+    0xAD: (0, 0, 0, 0, False, 'RES 5,L'),
+    0xAE: (0, 0, 1, 1, False, 'RES 5,(HL)'),
+    0xAF: (0, 0, 0, 0, False, 'RES 5,A'),
+
+    0xB0: (0, 0, 0, 0, False, 'RES 6,B'),
+    0xB1: (0, 0, 0, 0, False, 'RES 6,C'),
+    0xB2: (0, 0, 0, 0, False, 'RES 6,D'),
+    0xB3: (0, 0, 0, 0, False, 'RES 6,E'),
+    0xB4: (0, 0, 0, 0, False, 'RES 6,H'),
+    0xB5: (0, 0, 0, 0, False, 'RES 6,L'),
+    0xB6: (0, 0, 1, 1, False, 'RES 6,(HL)'),
+    0xB7: (0, 0, 0, 0, False, 'RES 6,A'),
+    0xB8: (0, 0, 0, 0, False, 'RES 7,B'),
+    0xB9: (0, 0, 0, 0, False, 'RES 7,C'),
+    0xBA: (0, 0, 0, 0, False, 'RES 7,D'),
+    0xBB: (0, 0, 0, 0, False, 'RES 7,E'),
+    0xBC: (0, 0, 0, 0, False, 'RES 7,H'),
+    0xBD: (0, 0, 0, 0, False, 'RES 7,L'),
+    0xBE: (0, 0, 1, 1, False, 'RES 7,(HL)'),
+    0xBF: (0, 0, 0, 0, False, 'RES 7,A'),
+
+    0xC0: (0, 0, 0, 0, False, 'SET 0,B'),
+    0xC1: (0, 0, 0, 0, False, 'SET 0,C'),
+    0xC2: (0, 0, 0, 0, False, 'SET 0,D'),
+    0xC3: (0, 0, 0, 0, False, 'SET 0,E'),
+    0xC4: (0, 0, 0, 0, False, 'SET 0,H'),
+    0xC5: (0, 0, 0, 0, False, 'SET 0,L'),
+    0xC6: (0, 0, 1, 1, False, 'SET 0,(HL)'),
+    0xC7: (0, 0, 0, 0, False, 'SET 0,A'),
+    0xC8: (0, 0, 0, 0, False, 'SET 1,B'),
+    0xC9: (0, 0, 0, 0, False, 'SET 1,C'),
+    0xCA: (0, 0, 0, 0, False, 'SET 1,D'),
+    0xCB: (0, 0, 0, 0, False, 'SET 1,E'),
+    0xCC: (0, 0, 0, 0, False, 'SET 1,H'),
+    0xCD: (0, 0, 0, 0, False, 'SET 1,L'),
+    0xCE: (0, 0, 1, 1, False, 'SET 1,(HL)'),
+    0xCF: (0, 0, 0, 0, False, 'SET 1,A'),
+
+    0xD0: (0, 0, 0, 0, False, 'SET 2,B'),
+    0xD1: (0, 0, 0, 0, False, 'SET 2,C'),
+    0xD2: (0, 0, 0, 0, False, 'SET 2,D'),
+    0xD3: (0, 0, 0, 0, False, 'SET 2,E'),
+    0xD4: (0, 0, 0, 0, False, 'SET 2,H'),
+    0xD5: (0, 0, 0, 0, False, 'SET 2,L'),
+    0xD6: (0, 0, 1, 1, False, 'SET 2,(HL)'),
+    0xD7: (0, 0, 0, 0, False, 'SET 2,A'),
+    0xD8: (0, 0, 0, 0, False, 'SET 3,B'),
+    0xD9: (0, 0, 0, 0, False, 'SET 3,C'),
+    0xDA: (0, 0, 0, 0, False, 'SET 3,D'),
+    0xDB: (0, 0, 0, 0, False, 'SET 3,E'),
+    0xDC: (0, 0, 0, 0, False, 'SET 3,H'),
+    0xDD: (0, 0, 0, 0, False, 'SET 3,L'),
+    0xDE: (0, 0, 1, 1, False, 'SET 3,(HL)'),
+    0xDF: (0, 0, 0, 0, False, 'SET 3,A'),
+
+    0xE0: (0, 0, 0, 0, False, 'SET 4,B'),
+    0xE1: (0, 0, 0, 0, False, 'SET 4,C'),
+    0xE2: (0, 0, 0, 0, False, 'SET 4,D'),
+    0xE3: (0, 0, 0, 0, False, 'SET 4,E'),
+    0xE4: (0, 0, 0, 0, False, 'SET 4,H'),
+    0xE5: (0, 0, 0, 0, False, 'SET 4,L'),
+    0xE6: (0, 0, 1, 1, False, 'SET 4,(HL)'),
+    0xE7: (0, 0, 0, 0, False, 'SET 4,A'),
+    0xE8: (0, 0, 0, 0, False, 'SET 5,B'),
+    0xE9: (0, 0, 0, 0, False, 'SET 5,C'),
+    0xEA: (0, 0, 0, 0, False, 'SET 5,D'),
+    0xEB: (0, 0, 0, 0, False, 'SET 5,E'),
+    0xEC: (0, 0, 0, 0, False, 'SET 5,H'),
+    0xED: (0, 0, 0, 0, False, 'SET 5,L'),
+    0xEE: (0, 0, 1, 1, False, 'SET 5,(HL)'),
+    0xEF: (0, 0, 0, 0, False, 'SET 5,A'),
+
+    0xF0: (0, 0, 0, 0, False, 'SET 6,B'),
+    0xF1: (0, 0, 0, 0, False, 'SET 6,C'),
+    0xF2: (0, 0, 0, 0, False, 'SET 6,D'),
+    0xF3: (0, 0, 0, 0, False, 'SET 6,E'),
+    0xF4: (0, 0, 0, 0, False, 'SET 6,H'),
+    0xF5: (0, 0, 0, 0, False, 'SET 6,L'),
+    0xF6: (0, 0, 1, 1, False, 'SET 6,(HL)'),
+    0xF7: (0, 0, 0, 0, False, 'SET 6,A'),
+    0xF8: (0, 0, 0, 0, False, 'SET 7,B'),
+    0xF9: (0, 0, 0, 0, False, 'SET 7,C'),
+    0xFA: (0, 0, 0, 0, False, 'SET 7,D'),
+    0xFB: (0, 0, 0, 0, False, 'SET 7,E'),
+    0xFC: (0, 0, 0, 0, False, 'SET 7,H'),
+    0xFD: (0, 0, 0, 0, False, 'SET 7,L'),
+    0xFE: (0, 0, 1, 1, False, 'SET 7,(HL)'),
+    0xFF: (0, 0, 0, 0, False, 'SET 7,A')
+}
+
+# Instructions with DD or FD prefix
+index_instructions = {
+    0x09: (0, 0, 0, 0, False, 'ADD {r},BC'),
+
+    0x19: (0, 0, 0, 0, False, 'ADD {r},DE'),
+
+    0x21: (0, 2, 0, 0, False, 'LD {r},{i:04X}h'),
+    0x22: (0, 2, 0, 2, False, 'LD ({i:04X}h),{r}'),
+    0x23: (0, 0, 0, 0, False, 'INC {r}'),
+    0x24: (0, 0, 0, 0, False, 'INC {r}h'),
+    0x25: (0, 0, 0, 0, False, 'DEC {r}h'),
+    0x26: (0, 1, 0, 0, False, 'LD {r}h,{i:02X}h'),
+
+    0x29: (0, 0, 0, 0, False, 'ADD {r},{r}'),
+    0x2A: (0, 2, 2, 0, False, 'LD {r},({i:04X}h)'),
+    0x2B: (0, 0, 0, 0, False, 'DEC {r}'),
+    0x2C: (0, 0, 0, 0, False, 'INC {r}l'),
+    0x2D: (0, 0, 0, 0, False, 'DEC {r}l'),
+    0x2E: (0, 1, 0, 0, False, 'LD {r}l,{i:02X}h'),
+
+    0x34: (1, 0, 1, 1, False, 'INC ({r}{d:+d})'),
+    0x35: (1, 0, 1, 1, False, 'DEC ({r}{d:+d})'),
+    0x36: (1, 1, 0, 1, False, 'LD ({r}{d:+d}),{i:02X}h'),
+
+    0x39: (0, 0, 0, 0, False, 'ADD {r},SP'),
+
+    0x44: (0, 0, 0, 0, False, 'LD B,{r}h'),
+    0x45: (0, 0, 0, 0, False, 'LD B,{r}l'),
+    0x46: (1, 0, 1, 0, False, 'LD B,({r}{d:+d})'),
+
+    0x4C: (0, 0, 0, 0, False, 'LD C,{r}h'),
+    0x4D: (0, 0, 0, 0, False, 'LD C,{r}l'),
+    0x4E: (1, 0, 1, 0, False, 'LD C,({r}{d:+d})'),
+
+    0x54: (0, 0, 0, 0, False, 'LD D,{r}h'),
+    0x55: (0, 0, 0, 0, False, 'LD D,{r}l'),
+    0x56: (1, 0, 1, 0, False, 'LD D,({r}{d:+d})'),
+
+    0x5C: (0, 0, 0, 0, False, 'LD E,{r}h'),
+    0x5D: (0, 0, 0, 0, False, 'LD E,{r}l'),
+    0x5E: (1, 0, 1, 0, False, 'LD E,({r}{d:+d})'),
+
+    0x60: (0, 0, 0, 0, False, 'LD {r}h,B'),
+    0x61: (0, 0, 0, 0, False, 'LD {r}h,C'),
+    0x62: (0, 0, 0, 0, False, 'LD {r}h,D'),
+    0x63: (0, 0, 0, 0, False, 'LD {r}h,E'),
+    0x64: (0, 0, 0, 0, False, 'LD {r}h,{r}h'),
+    0x65: (0, 0, 0, 0, False, 'LD {r}h,{r}l'),
+    0x66: (1, 0, 1, 0, False, 'LD H,({r}{d:+d})'),
+    0x67: (0, 0, 0, 0, False, 'LD {r}h,A'),
+    0x68: (0, 0, 0, 0, False, 'LD {r}l,B'),
+    0x69: (0, 0, 0, 0, False, 'LD {r}l,C'),
+    0x6A: (0, 0, 0, 0, False, 'LD {r}l,D'),
+    0x6B: (0, 0, 0, 0, False, 'LD {r}l,E'),
+    0x6C: (0, 0, 0, 0, False, 'LD {r}l,{r}h'),
+    0x6D: (0, 0, 0, 0, False, 'LD {r}l,{r}l'),
+    0x6E: (1, 0, 1, 0, False, 'LD L,({r}{d:+d})'),
+    0x6F: (0, 0, 0, 0, False, 'LD {r}l,A'),
+
+    0x70: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),B'),
+    0x71: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),C'),
+    0x72: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),D'),
+    0x73: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),E'),
+    0x74: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),H'),
+    0x75: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),L'),
+
+    0x77: (1, 0, 0, 1, False, 'LD ({r}{d:+d}),A'),
+
+    0x7C: (0, 0, 0, 0, False, 'LD A,{r}h'),
+    0x7D: (0, 0, 0, 0, False, 'LD A,{r}l'),
+    0x7E: (1, 0, 1, 0, False, 'LD A,({r}{d:+d})'),
+
+    0x84: (0, 0, 0, 0, False, 'ADD A,{r}h'),
+    0x85: (0, 0, 0, 0, False, 'ADD A,{r}l'),
+    0x86: (1, 0, 1, 0, False, 'ADD A,({r}{d:+d})'),
+
+    0x8C: (0, 0, 0, 0, False, 'ADC A,{r}h'),
+    0x8D: (0, 0, 0, 0, False, 'ADC A,{r}l'),
+    0x8E: (1, 0, 1, 0, False, 'ADC A,({r}{d:+d})'),
+
+    0x94: (0, 0, 0, 0, False, 'SUB {r}h'),
+    0x95: (0, 0, 0, 0, False, 'SUB {r}l'),
+    0x96: (1, 0, 1, 0, False, 'SUB ({r}{d:+d})'),
+
+    0x9C: (0, 0, 0, 0, False, 'SBC A,{r}h'),
+    0x9D: (0, 0, 0, 0, False, 'SBC A,{r}l'),
+    0x9E: (1, 0, 1, 0, False, 'SBC A,({r}{d:+d})'),
+
+    0xA4: (0, 0, 0, 0, False, 'AND {r}h'),
+    0xA5: (0, 0, 0, 0, False, 'AND {r}l'),
+    0xA6: (1, 0, 1, 0, False, 'AND ({r}{d:+d})'),
+
+    0xAC: (0, 0, 0, 0, False, 'XOR {r}h'),
+    0xAD: (0, 0, 0, 0, False, 'XOR {r}l'),
+    0xAE: (1, 0, 1, 0, False, 'XOR ({r}{d:+d})'),
+
+    0xB4: (0, 0, 0, 0, False, 'OR {r}h'),
+    0xB5: (0, 0, 0, 0, False, 'OR {r}l'),
+    0xB6: (1, 0, 1, 0, False, 'OR ({r}{d:+d})'),
+
+    0xBC: (0, 0, 0, 0, False, 'CP {r}h'),
+    0xBD: (0, 0, 0, 0, False, 'CP {r}l'),
+    0xBE: (1, 0, 1, 0, False, 'CP ({r}{d:+d})'),
+
+    0xE1: (0, 0, 2, 0, False, 'POP {r}'),
+
+    0xE3: (0, 0, 2, 2, False, 'EX (SP),{r}'),
+
+    0xE5: (0, 0, 0,-2, False, 'PUSH {r}'),
+
+    0xE9: (0, 0, 0, 0, False, 'JP ({r})'),
+
+    0xF9: (0, 0, 0, 0, False, 'LD SP,{r}')
+}
+
+# Instructions with DD CB or FD CB prefix.
+# For these instructions, the displacement precedes the opcode byte.
+# This is handled as a special case in the code, and thus the entries
+# in this table specify 0 for the displacement length.
+index_bit_instructions = {
+    0x00: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),B'),
+    0x01: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),C'),
+    0x02: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),D'),
+    0x03: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),E'),
+    0x04: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),H'),
+    0x05: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),L'),
+    0x06: (0, 0, 1, 1, False, 'RLC ({r}{d:+d})'),
+    0x07: (0, 0, 1, 1, False, 'RLC ({r}{d:+d}),A'),
+    0x08: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),B'),
+    0x09: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),C'),
+    0x0A: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),D'),
+    0x0B: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),E'),
+    0x0C: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),H'),
+    0x0D: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),L'),
+    0x0E: (0, 0, 1, 1, False, 'RRC ({r}{d:+d})'),
+    0x0F: (0, 0, 1, 1, False, 'RRC ({r}{d:+d}),A'),
+
+    0x10: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),B'),
+    0x11: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),C'),
+    0x12: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),D'),
+    0x13: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),E'),
+    0x14: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),H'),
+    0x15: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),L'),
+    0x16: (0, 0, 1, 1, False, 'RL ({r}{d:+d})'),
+    0x17: (0, 0, 1, 1, False, 'RL ({r}{d:+d}),A'),
+    0x18: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),B'),
+    0x19: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),C'),
+    0x1A: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),D'),
+    0x1B: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),E'),
+    0x1C: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),H'),
+    0x1D: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),L'),
+    0x1E: (0, 0, 1, 1, False, 'RR ({r}{d:+d})'),
+    0x1F: (0, 0, 1, 1, False, 'RR ({r}{d:+d}),A'),
+
+    0x20: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),B'),
+    0x21: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),C'),
+    0x22: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),D'),
+    0x23: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),E'),
+    0x24: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),H'),
+    0x25: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),L'),
+    0x26: (0, 0, 1, 1, False, 'SLA ({r}{d:+d})'),
+    0x27: (0, 0, 1, 1, False, 'SLA ({r}{d:+d}),A'),
+    0x28: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),B'),
+    0x29: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),C'),
+    0x2A: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),D'),
+    0x2B: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),E'),
+    0x2C: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),H'),
+    0x2D: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),L'),
+    0x2E: (0, 0, 1, 1, False, 'SRA ({r}{d:+d})'),
+    0x2F: (0, 0, 1, 1, False, 'SRA ({r}{d:+d}),A'),
+
+    0x30: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),B'),
+    0x31: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),C'),
+    0x32: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),D'),
+    0x33: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),E'),
+    0x34: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),H'),
+    0x35: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),L'),
+    0x36: (0, 0, 1, 1, False, 'SLL ({r}{d:+d})'),
+    0x37: (0, 0, 1, 1, False, 'SLL ({r}{d:+d}),A'),
+    0x38: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),B'),
+    0x39: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),C'),
+    0x3A: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),D'),
+    0x3B: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),E'),
+    0x3C: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),H'),
+    0x3D: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),L'),
+    0x3E: (0, 0, 1, 1, False, 'SRL ({r}{d:+d})'),
+    0x3F: (0, 0, 1, 1, False, 'SRL ({r}{d:+d}),A'),
+
+    0x40: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x41: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x42: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x43: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x44: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x45: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x46: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x47: (0, 0, 1, 0, False, 'BIT 0,({r}{d:+d})'),
+    0x48: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x49: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x4A: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x4B: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x4C: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x4D: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x4E: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+    0x4F: (0, 0, 1, 0, False, 'BIT 1,({r}{d:+d})'),
+
+    0x50: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x51: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x52: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x53: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x54: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x55: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x56: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x57: (0, 0, 1, 0, False, 'BIT 2,({r}{d:+d})'),
+    0x58: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x59: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x5A: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x5B: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x5C: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x5D: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x5E: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+    0x5F: (0, 0, 1, 0, False, 'BIT 3,({r}{d:+d})'),
+
+    0x60: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x61: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x62: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x63: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x64: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x65: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x66: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x67: (0, 0, 1, 0, False, 'BIT 4,({r}{d:+d})'),
+    0x68: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x69: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x6A: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x6B: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x6C: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x6D: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x6E: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+    0x6F: (0, 0, 1, 0, False, 'BIT 5,({r}{d:+d})'),
+
+    0x70: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x71: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x72: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x73: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x74: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x75: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x76: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x77: (0, 0, 1, 0, False, 'BIT 6,({r}{d:+d})'),
+    0x78: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x79: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x7A: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x7B: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x7C: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x7D: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x7E: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+    0x7F: (0, 0, 1, 0, False, 'BIT 7,({r}{d:+d})'),
+
+    0x80: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),B'),
+    0x81: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),C'),
+    0x82: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),D'),
+    0x83: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),E'),
+    0x84: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),H'),
+    0x85: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),L'),
+    0x86: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d})'),
+    0x87: (0, 0, 1, 1, False, 'RES 0,({r}{d:+d}),A'),
+    0x88: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),B'),
+    0x89: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),C'),
+    0x8A: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),D'),
+    0x8B: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),E'),
+    0x8C: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),H'),
+    0x8D: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),L'),
+    0x8E: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d})'),
+    0x8F: (0, 0, 1, 1, False, 'RES 1,({r}{d:+d}),A'),
+
+    0x90: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),B'),
+    0x91: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),C'),
+    0x92: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),D'),
+    0x93: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),E'),
+    0x94: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),H'),
+    0x95: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),L'),
+    0x96: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d})'),
+    0x97: (0, 0, 1, 1, False, 'RES 2,({r}{d:+d}),A'),
+    0x98: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),B'),
+    0x99: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),C'),
+    0x9A: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),D'),
+    0x9B: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),E'),
+    0x9C: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),H'),
+    0x9D: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),L'),
+    0x9E: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d})'),
+    0x9F: (0, 0, 1, 1, False, 'RES 3,({r}{d:+d}),A'),
+
+    0xA0: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),B'),
+    0xA1: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),C'),
+    0xA2: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),D'),
+    0xA3: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),E'),
+    0xA4: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),H'),
+    0xA5: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),L'),
+    0xA6: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d})'),
+    0xA7: (0, 0, 1, 1, False, 'RES 4,({r}{d:+d}),A'),
+    0xA8: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),B'),
+    0xA9: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),C'),
+    0xAA: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),D'),
+    0xAB: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),E'),
+    0xAC: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),H'),
+    0xAD: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),L'),
+    0xAE: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d})'),
+    0xAF: (0, 0, 1, 1, False, 'RES 5,({r}{d:+d}),A'),
+
+    0xB0: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),B'),
+    0xB1: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),C'),
+    0xB2: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),D'),
+    0xB3: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),E'),
+    0xB4: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),H'),
+    0xB5: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),L'),
+    0xB6: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d})'),
+    0xB7: (0, 0, 1, 1, False, 'RES 6,({r}{d:+d}),A'),
+    0xB8: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),B'),
+    0xB9: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),C'),
+    0xBA: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),D'),
+    0xBB: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),E'),
+    0xBC: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),H'),
+    0xBD: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),L'),
+    0xBE: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d})'),
+    0xBF: (0, 0, 1, 1, False, 'RES 7,({r}{d:+d}),A'),
+
+    0xC0: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),B'),
+    0xC1: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),C'),
+    0xC2: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),D'),
+    0xC3: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),E'),
+    0xC4: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),H'),
+    0xC5: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),L'),
+    0xC6: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d})'),
+    0xC7: (0, 0, 1, 1, False, 'SET 0,({r}{d:+d}),A'),
+    0xC8: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),B'),
+    0xC9: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),C'),
+    0xCA: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),D'),
+    0xCB: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),E'),
+    0xCC: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),H'),
+    0xCD: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),L'),
+    0xCE: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d})'),
+    0xCF: (0, 0, 1, 1, False, 'SET 1,({r}{d:+d}),A'),
+
+    0xD0: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),B'),
+    0xD1: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),C'),
+    0xD2: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),D'),
+    0xD3: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),E'),
+    0xD4: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),H'),
+    0xD5: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),L'),
+    0xD6: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d})'),
+    0xD7: (0, 0, 1, 1, False, 'SET 2,({r}{d:+d}),A'),
+    0xD8: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),B'),
+    0xD9: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),C'),
+    0xDA: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),D'),
+    0xDB: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),E'),
+    0xDC: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),H'),
+    0xDD: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),L'),
+    0xDE: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d})'),
+    0xDF: (0, 0, 1, 1, False, 'SET 3,({r}{d:+d}),A'),
+
+    0xE0: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),B'),
+    0xE1: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),C'),
+    0xE2: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),D'),
+    0xE3: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),E'),
+    0xE4: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),H'),
+    0xE5: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),L'),
+    0xE6: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d})'),
+    0xE7: (0, 0, 1, 1, False, 'SET 4,({r}{d:+d}),A'),
+    0xE8: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),B'),
+    0xE9: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),C'),
+    0xEA: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),D'),
+    0xEB: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),E'),
+    0xEC: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),H'),
+    0xED: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),L'),
+    0xEE: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d})'),
+    0xEF: (0, 0, 1, 1, False, 'SET 5,({r}{d:+d}),A'),
+
+    0xF0: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),B'),
+    0xF1: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),C'),
+    0xF2: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),D'),
+    0xF3: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),E'),
+    0xF4: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),H'),
+    0xF5: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),L'),
+    0xF6: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d})'),
+    0xF7: (0, 0, 1, 1, False, 'SET 6,({r}{d:+d}),A'),
+    0xF8: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),B'),
+    0xF9: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),C'),
+    0xFA: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),D'),
+    0xFB: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),E'),
+    0xFC: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),H'),
+    0xFD: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),L'),
+    0xFE: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d})'),
+    0xFF: (0, 0, 1, 1, False, 'SET 7,({r}{d:+d}),A')
+}
+
+instr_table_by_prefix = {
+    0:      (main_instructions,      ''),
+    0xED:   (extended_instructions,  ''),
+    0xCB:   (bit_instructions,       ''),
+    0xDD:   (index_instructions,     'IX'),
+    0xFD:   (index_instructions,     'IY'),
+    0xDDCB: (index_bit_instructions, 'IX'),
+    0xFDCB: (index_bit_instructions, 'IY')
+}