Handle DDCB and FDCB instructions including undocumented variants
authorNick Downing <nick@ndcode.org>
Thu, 21 Jul 2022 13:05:02 +0000 (23:05 +1000)
committerNick Downing <nick@ndcode.org>
Thu, 21 Jul 2022 13:05:02 +0000 (23:05 +1000)
cpu_z80.c
cpu_z80.h
decode_65c02.py
decode_65c02.sed
decode_z80.py
decode_z80.sed

index e17f2e4..6a866bf 100644 (file)
--- a/cpu_z80.c
+++ b/cpu_z80.c
@@ -797,196 +797,196 @@ void cpu_z80_execute(struct cpu_z80 *self) {
 void cpu_z80_execute_cb(struct cpu_z80 *self) {
   switch (cpu_z80_fetch_byte(self)) {
   case 0x00:
-    cpu_z80_rlc(self, CPU_Z80_EA_B);
+    cpu_z80_rlc(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x01:
-    cpu_z80_rlc(self, CPU_Z80_EA_C);
+    cpu_z80_rlc(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x02:
-    cpu_z80_rlc(self, CPU_Z80_EA_D);
+    cpu_z80_rlc(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x03:
-    cpu_z80_rlc(self, CPU_Z80_EA_E);
+    cpu_z80_rlc(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x04:
-    cpu_z80_rlc(self, CPU_Z80_EA_H);
+    cpu_z80_rlc(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x05:
-    cpu_z80_rlc(self, CPU_Z80_EA_L);
+    cpu_z80_rlc(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x06:
-    cpu_z80_rlc(self, self->regs.word.hl);
+    cpu_z80_rlc(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x07:
-    cpu_z80_rlc(self, CPU_Z80_EA_A);
+    cpu_z80_rlc(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x08:
-    cpu_z80_rrc(self, CPU_Z80_EA_B);
+    cpu_z80_rrc(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x09:
-    cpu_z80_rrc(self, CPU_Z80_EA_C);
+    cpu_z80_rrc(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x0a:
-    cpu_z80_rrc(self, CPU_Z80_EA_D);
+    cpu_z80_rrc(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x0b:
-    cpu_z80_rrc(self, CPU_Z80_EA_E);
+    cpu_z80_rrc(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x0c:
-    cpu_z80_rrc(self, CPU_Z80_EA_H);
+    cpu_z80_rrc(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x0d:
-    cpu_z80_rrc(self, CPU_Z80_EA_L);
+    cpu_z80_rrc(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x0e:
-    cpu_z80_rrc(self, self->regs.word.hl);
+    cpu_z80_rrc(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x0f:
-    cpu_z80_rrc(self, CPU_Z80_EA_A);
+    cpu_z80_rrc(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x10:
-    cpu_z80_rl(self, CPU_Z80_EA_B);
+    cpu_z80_rl(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x11:
-    cpu_z80_rl(self, CPU_Z80_EA_C);
+    cpu_z80_rl(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x12:
-    cpu_z80_rl(self, CPU_Z80_EA_D);
+    cpu_z80_rl(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x13:
-    cpu_z80_rl(self, CPU_Z80_EA_E);
+    cpu_z80_rl(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x14:
-    cpu_z80_rl(self, CPU_Z80_EA_H);
+    cpu_z80_rl(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x15:
-    cpu_z80_rl(self, CPU_Z80_EA_L);
+    cpu_z80_rl(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x16:
-    cpu_z80_rl(self, self->regs.word.hl);
+    cpu_z80_rl(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x17:
-    cpu_z80_rl(self, CPU_Z80_EA_A);
+    cpu_z80_rl(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x18:
-    cpu_z80_rr(self, CPU_Z80_EA_B);
+    cpu_z80_rr(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x19:
-    cpu_z80_rr(self, CPU_Z80_EA_C);
+    cpu_z80_rr(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x1a:
-    cpu_z80_rr(self, CPU_Z80_EA_D);
+    cpu_z80_rr(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x1b:
-    cpu_z80_rr(self, CPU_Z80_EA_E);
+    cpu_z80_rr(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x1c:
-    cpu_z80_rr(self, CPU_Z80_EA_H);
+    cpu_z80_rr(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x1d:
-    cpu_z80_rr(self, CPU_Z80_EA_L);
+    cpu_z80_rr(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x1e:
-    cpu_z80_rr(self, self->regs.word.hl);
+    cpu_z80_rr(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x1f:
-    cpu_z80_rr(self, CPU_Z80_EA_A);
+    cpu_z80_rr(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x20:
-    cpu_z80_sla(self, CPU_Z80_EA_B);
+    cpu_z80_sla(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x21:
-    cpu_z80_sla(self, CPU_Z80_EA_C);
+    cpu_z80_sla(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x22:
-    cpu_z80_sla(self, CPU_Z80_EA_D);
+    cpu_z80_sla(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x23:
-    cpu_z80_sla(self, CPU_Z80_EA_E);
+    cpu_z80_sla(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x24:
-    cpu_z80_sla(self, CPU_Z80_EA_H);
+    cpu_z80_sla(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x25:
-    cpu_z80_sla(self, CPU_Z80_EA_L);
+    cpu_z80_sla(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x26:
-    cpu_z80_sla(self, self->regs.word.hl);
+    cpu_z80_sla(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x27:
-    cpu_z80_sla(self, CPU_Z80_EA_A);
+    cpu_z80_sla(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x28:
-    cpu_z80_sra(self, CPU_Z80_EA_B);
+    cpu_z80_sra(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x29:
-    cpu_z80_sra(self, CPU_Z80_EA_C);
+    cpu_z80_sra(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x2a:
-    cpu_z80_sra(self, CPU_Z80_EA_D);
+    cpu_z80_sra(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x2b:
-    cpu_z80_sra(self, CPU_Z80_EA_E);
+    cpu_z80_sra(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x2c:
-    cpu_z80_sra(self, CPU_Z80_EA_H);
+    cpu_z80_sra(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x2d:
-    cpu_z80_sra(self, CPU_Z80_EA_L);
+    cpu_z80_sra(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x2e:
-    cpu_z80_sra(self, self->regs.word.hl);
+    cpu_z80_sra(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x2f:
-    cpu_z80_sra(self, CPU_Z80_EA_A);
+    cpu_z80_sra(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x30:
-    cpu_z80_sll(self, CPU_Z80_EA_B);
+    cpu_z80_sll(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x31:
-    cpu_z80_sll(self, CPU_Z80_EA_C);
+    cpu_z80_sll(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x32:
-    cpu_z80_sll(self, CPU_Z80_EA_D);
+    cpu_z80_sll(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x33:
-    cpu_z80_sll(self, CPU_Z80_EA_E);
+    cpu_z80_sll(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x34:
-    cpu_z80_sll(self, CPU_Z80_EA_H);
+    cpu_z80_sll(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x35:
-    cpu_z80_sll(self, CPU_Z80_EA_L);
+    cpu_z80_sll(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x36:
-    cpu_z80_sll(self, self->regs.word.hl);
+    cpu_z80_sll(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x37:
-    cpu_z80_sll(self, CPU_Z80_EA_A);
+    cpu_z80_sll(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x38:
-    cpu_z80_srl(self, CPU_Z80_EA_B);
+    cpu_z80_srl(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x39:
-    cpu_z80_srl(self, CPU_Z80_EA_C);
+    cpu_z80_srl(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x3a:
-    cpu_z80_srl(self, CPU_Z80_EA_D);
+    cpu_z80_srl(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x3b:
-    cpu_z80_srl(self, CPU_Z80_EA_E);
+    cpu_z80_srl(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x3c:
-    cpu_z80_srl(self, CPU_Z80_EA_H);
+    cpu_z80_srl(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x3d:
-    cpu_z80_srl(self, CPU_Z80_EA_L);
+    cpu_z80_srl(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x3e:
-    cpu_z80_srl(self, self->regs.word.hl);
+    cpu_z80_srl(self, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x3f:
-    cpu_z80_srl(self, CPU_Z80_EA_A);
+    cpu_z80_srl(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x40:
     cpu_z80_bit(self, 0, self->regs.byte.b);
@@ -1181,388 +1181,388 @@ void cpu_z80_execute_cb(struct cpu_z80 *self) {
     cpu_z80_bit(self, 7, self->regs.byte.a);
     break;
   case 0x80:
-    cpu_z80_res(self, 0, CPU_Z80_EA_B);
+    cpu_z80_res(self, 0, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x81:
-    cpu_z80_res(self, 0, CPU_Z80_EA_C);
+    cpu_z80_res(self, 0, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x82:
-    cpu_z80_res(self, 0, CPU_Z80_EA_D);
+    cpu_z80_res(self, 0, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x83:
-    cpu_z80_res(self, 0, CPU_Z80_EA_E);
+    cpu_z80_res(self, 0, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x84:
-    cpu_z80_res(self, 0, CPU_Z80_EA_H);
+    cpu_z80_res(self, 0, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x85:
-    cpu_z80_res(self, 0, CPU_Z80_EA_L);
+    cpu_z80_res(self, 0, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x86:
-    cpu_z80_res(self, 0, self->regs.word.hl);
+    cpu_z80_res(self, 0, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x87:
-    cpu_z80_res(self, 0, CPU_Z80_EA_A);
+    cpu_z80_res(self, 0, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x88:
-    cpu_z80_res(self, 1, CPU_Z80_EA_B);
+    cpu_z80_res(self, 1, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x89:
-    cpu_z80_res(self, 1, CPU_Z80_EA_C);
+    cpu_z80_res(self, 1, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x8a:
-    cpu_z80_res(self, 1, CPU_Z80_EA_D);
+    cpu_z80_res(self, 1, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x8b:
-    cpu_z80_res(self, 1, CPU_Z80_EA_E);
+    cpu_z80_res(self, 1, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x8c:
-    cpu_z80_res(self, 1, CPU_Z80_EA_H);
+    cpu_z80_res(self, 1, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x8d:
-    cpu_z80_res(self, 1, CPU_Z80_EA_L);
+    cpu_z80_res(self, 1, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x8e:
-    cpu_z80_res(self, 1, self->regs.word.hl);
+    cpu_z80_res(self, 1, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x8f:
-    cpu_z80_res(self, 1, CPU_Z80_EA_A);
+    cpu_z80_res(self, 1, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x90:
-    cpu_z80_res(self, 2, CPU_Z80_EA_B);
+    cpu_z80_res(self, 2, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x91:
-    cpu_z80_res(self, 2, CPU_Z80_EA_C);
+    cpu_z80_res(self, 2, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x92:
-    cpu_z80_res(self, 2, CPU_Z80_EA_D);
+    cpu_z80_res(self, 2, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x93:
-    cpu_z80_res(self, 2, CPU_Z80_EA_E);
+    cpu_z80_res(self, 2, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x94:
-    cpu_z80_res(self, 2, CPU_Z80_EA_H);
+    cpu_z80_res(self, 2, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x95:
-    cpu_z80_res(self, 2, CPU_Z80_EA_L);
+    cpu_z80_res(self, 2, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x96:
-    cpu_z80_res(self, 2, self->regs.word.hl);
+    cpu_z80_res(self, 2, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x97:
-    cpu_z80_res(self, 2, CPU_Z80_EA_A);
+    cpu_z80_res(self, 2, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0x98:
-    cpu_z80_res(self, 3, CPU_Z80_EA_B);
+    cpu_z80_res(self, 3, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0x99:
-    cpu_z80_res(self, 3, CPU_Z80_EA_C);
+    cpu_z80_res(self, 3, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0x9a:
-    cpu_z80_res(self, 3, CPU_Z80_EA_D);
+    cpu_z80_res(self, 3, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0x9b:
-    cpu_z80_res(self, 3, CPU_Z80_EA_E);
+    cpu_z80_res(self, 3, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0x9c:
-    cpu_z80_res(self, 3, CPU_Z80_EA_H);
+    cpu_z80_res(self, 3, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0x9d:
-    cpu_z80_res(self, 3, CPU_Z80_EA_L);
+    cpu_z80_res(self, 3, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0x9e:
-    cpu_z80_res(self, 3, self->regs.word.hl);
+    cpu_z80_res(self, 3, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0x9f:
-    cpu_z80_res(self, 3, CPU_Z80_EA_A);
+    cpu_z80_res(self, 3, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xa0:
-    cpu_z80_res(self, 4, CPU_Z80_EA_B);
+    cpu_z80_res(self, 4, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xa1:
-    cpu_z80_res(self, 4, CPU_Z80_EA_C);
+    cpu_z80_res(self, 4, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xa2:
-    cpu_z80_res(self, 4, CPU_Z80_EA_D);
+    cpu_z80_res(self, 4, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xa3:
-    cpu_z80_res(self, 4, CPU_Z80_EA_E);
+    cpu_z80_res(self, 4, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xa4:
-    cpu_z80_res(self, 4, CPU_Z80_EA_H);
+    cpu_z80_res(self, 4, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xa5:
-    cpu_z80_res(self, 4, CPU_Z80_EA_L);
+    cpu_z80_res(self, 4, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xa6:
-    cpu_z80_res(self, 4, self->regs.word.hl);
+    cpu_z80_res(self, 4, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xa7:
-    cpu_z80_res(self, 4, CPU_Z80_EA_A);
+    cpu_z80_res(self, 4, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xa8:
-    cpu_z80_res(self, 5, CPU_Z80_EA_B);
+    cpu_z80_res(self, 5, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xa9:
-    cpu_z80_res(self, 5, CPU_Z80_EA_C);
+    cpu_z80_res(self, 5, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xaa:
-    cpu_z80_res(self, 5, CPU_Z80_EA_D);
+    cpu_z80_res(self, 5, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xab:
-    cpu_z80_res(self, 5, CPU_Z80_EA_E);
+    cpu_z80_res(self, 5, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xac:
-    cpu_z80_res(self, 5, CPU_Z80_EA_H);
+    cpu_z80_res(self, 5, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xad:
-    cpu_z80_res(self, 5, CPU_Z80_EA_L);
+    cpu_z80_res(self, 5, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xae:
-    cpu_z80_res(self, 5, self->regs.word.hl);
+    cpu_z80_res(self, 5, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xaf:
-    cpu_z80_res(self, 5, CPU_Z80_EA_A);
+    cpu_z80_res(self, 5, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xb0:
-    cpu_z80_res(self, 6, CPU_Z80_EA_B);
+    cpu_z80_res(self, 6, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xb1:
-    cpu_z80_res(self, 6, CPU_Z80_EA_C);
+    cpu_z80_res(self, 6, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xb2:
-    cpu_z80_res(self, 6, CPU_Z80_EA_D);
+    cpu_z80_res(self, 6, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xb3:
-    cpu_z80_res(self, 6, CPU_Z80_EA_E);
+    cpu_z80_res(self, 6, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xb4:
-    cpu_z80_res(self, 6, CPU_Z80_EA_H);
+    cpu_z80_res(self, 6, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xb5:
-    cpu_z80_res(self, 6, CPU_Z80_EA_L);
+    cpu_z80_res(self, 6, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xb6:
-    cpu_z80_res(self, 6, self->regs.word.hl);
+    cpu_z80_res(self, 6, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xb7:
-    cpu_z80_res(self, 6, CPU_Z80_EA_A);
+    cpu_z80_res(self, 6, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xb8:
-    cpu_z80_res(self, 7, CPU_Z80_EA_B);
+    cpu_z80_res(self, 7, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xb9:
-    cpu_z80_res(self, 7, CPU_Z80_EA_C);
+    cpu_z80_res(self, 7, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xba:
-    cpu_z80_res(self, 7, CPU_Z80_EA_D);
+    cpu_z80_res(self, 7, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xbb:
-    cpu_z80_res(self, 7, CPU_Z80_EA_E);
+    cpu_z80_res(self, 7, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xbc:
-    cpu_z80_res(self, 7, CPU_Z80_EA_H);
+    cpu_z80_res(self, 7, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xbd:
-    cpu_z80_res(self, 7, CPU_Z80_EA_L);
+    cpu_z80_res(self, 7, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xbe:
-    cpu_z80_res(self, 7, self->regs.word.hl);
+    cpu_z80_res(self, 7, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xbf:
-    cpu_z80_res(self, 7, CPU_Z80_EA_A);
+    cpu_z80_res(self, 7, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xc0:
-    cpu_z80_set(self, 0, CPU_Z80_EA_B);
+    cpu_z80_set(self, 0, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xc1:
-    cpu_z80_set(self, 0, CPU_Z80_EA_C);
+    cpu_z80_set(self, 0, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xc2:
-    cpu_z80_set(self, 0, CPU_Z80_EA_D);
+    cpu_z80_set(self, 0, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xc3:
-    cpu_z80_set(self, 0, CPU_Z80_EA_E);
+    cpu_z80_set(self, 0, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xc4:
-    cpu_z80_set(self, 0, CPU_Z80_EA_H);
+    cpu_z80_set(self, 0, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xc5:
-    cpu_z80_set(self, 0, CPU_Z80_EA_L);
+    cpu_z80_set(self, 0, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xc6:
-    cpu_z80_set(self, 0, self->regs.word.hl);
+    cpu_z80_set(self, 0, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xc7:
-    cpu_z80_set(self, 0, CPU_Z80_EA_A);
+    cpu_z80_set(self, 0, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xc8:
-    cpu_z80_set(self, 1, CPU_Z80_EA_B);
+    cpu_z80_set(self, 1, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xc9:
-    cpu_z80_set(self, 1, CPU_Z80_EA_C);
+    cpu_z80_set(self, 1, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xca:
-    cpu_z80_set(self, 1, CPU_Z80_EA_D);
+    cpu_z80_set(self, 1, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xcb:
-    cpu_z80_set(self, 1, CPU_Z80_EA_E);
+    cpu_z80_set(self, 1, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xcc:
-    cpu_z80_set(self, 1, CPU_Z80_EA_H);
+    cpu_z80_set(self, 1, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xcd:
-    cpu_z80_set(self, 1, CPU_Z80_EA_L);
+    cpu_z80_set(self, 1, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xce:
-    cpu_z80_set(self, 1, self->regs.word.hl);
+    cpu_z80_set(self, 1, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xcf:
-    cpu_z80_set(self, 1, CPU_Z80_EA_A);
+    cpu_z80_set(self, 1, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xd0:
-    cpu_z80_set(self, 2, CPU_Z80_EA_B);
+    cpu_z80_set(self, 2, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xd1:
-    cpu_z80_set(self, 2, CPU_Z80_EA_C);
+    cpu_z80_set(self, 2, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xd2:
-    cpu_z80_set(self, 2, CPU_Z80_EA_D);
+    cpu_z80_set(self, 2, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xd3:
-    cpu_z80_set(self, 2, CPU_Z80_EA_E);
+    cpu_z80_set(self, 2, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xd4:
-    cpu_z80_set(self, 2, CPU_Z80_EA_H);
+    cpu_z80_set(self, 2, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xd5:
-    cpu_z80_set(self, 2, CPU_Z80_EA_L);
+    cpu_z80_set(self, 2, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xd6:
-    cpu_z80_set(self, 2, self->regs.word.hl);
+    cpu_z80_set(self, 2, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xd7:
-    cpu_z80_set(self, 2, CPU_Z80_EA_A);
+    cpu_z80_set(self, 2, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xd8:
-    cpu_z80_set(self, 3, CPU_Z80_EA_B);
+    cpu_z80_set(self, 3, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xd9:
-    cpu_z80_set(self, 3, CPU_Z80_EA_C);
+    cpu_z80_set(self, 3, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xda:
-    cpu_z80_set(self, 3, CPU_Z80_EA_D);
+    cpu_z80_set(self, 3, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xdb:
-    cpu_z80_set(self, 3, CPU_Z80_EA_E);
+    cpu_z80_set(self, 3, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xdc:
-    cpu_z80_set(self, 3, CPU_Z80_EA_H);
+    cpu_z80_set(self, 3, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xdd:
-    cpu_z80_set(self, 3, CPU_Z80_EA_L);
+    cpu_z80_set(self, 3, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xde:
-    cpu_z80_set(self, 3, self->regs.word.hl);
+    cpu_z80_set(self, 3, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xdf:
-    cpu_z80_set(self, 3, CPU_Z80_EA_A);
+    cpu_z80_set(self, 3, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xe0:
-    cpu_z80_set(self, 4, CPU_Z80_EA_B);
+    cpu_z80_set(self, 4, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xe1:
-    cpu_z80_set(self, 4, CPU_Z80_EA_C);
+    cpu_z80_set(self, 4, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xe2:
-    cpu_z80_set(self, 4, CPU_Z80_EA_D);
+    cpu_z80_set(self, 4, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xe3:
-    cpu_z80_set(self, 4, CPU_Z80_EA_E);
+    cpu_z80_set(self, 4, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xe4:
-    cpu_z80_set(self, 4, CPU_Z80_EA_H);
+    cpu_z80_set(self, 4, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xe5:
-    cpu_z80_set(self, 4, CPU_Z80_EA_L);
+    cpu_z80_set(self, 4, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xe6:
-    cpu_z80_set(self, 4, self->regs.word.hl);
+    cpu_z80_set(self, 4, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xe7:
-    cpu_z80_set(self, 4, CPU_Z80_EA_A);
+    cpu_z80_set(self, 4, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xe8:
-    cpu_z80_set(self, 5, CPU_Z80_EA_B);
+    cpu_z80_set(self, 5, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xe9:
-    cpu_z80_set(self, 5, CPU_Z80_EA_C);
+    cpu_z80_set(self, 5, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xea:
-    cpu_z80_set(self, 5, CPU_Z80_EA_D);
+    cpu_z80_set(self, 5, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xeb:
-    cpu_z80_set(self, 5, CPU_Z80_EA_E);
+    cpu_z80_set(self, 5, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xec:
-    cpu_z80_set(self, 5, CPU_Z80_EA_H);
+    cpu_z80_set(self, 5, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xed:
-    cpu_z80_set(self, 5, CPU_Z80_EA_L);
+    cpu_z80_set(self, 5, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xee:
-    cpu_z80_set(self, 5, self->regs.word.hl);
+    cpu_z80_set(self, 5, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xef:
-    cpu_z80_set(self, 5, CPU_Z80_EA_A);
+    cpu_z80_set(self, 5, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xf0:
-    cpu_z80_set(self, 6, CPU_Z80_EA_B);
+    cpu_z80_set(self, 6, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xf1:
-    cpu_z80_set(self, 6, CPU_Z80_EA_C);
+    cpu_z80_set(self, 6, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xf2:
-    cpu_z80_set(self, 6, CPU_Z80_EA_D);
+    cpu_z80_set(self, 6, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xf3:
-    cpu_z80_set(self, 6, CPU_Z80_EA_E);
+    cpu_z80_set(self, 6, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xf4:
-    cpu_z80_set(self, 6, CPU_Z80_EA_H);
+    cpu_z80_set(self, 6, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xf5:
-    cpu_z80_set(self, 6, CPU_Z80_EA_L);
+    cpu_z80_set(self, 6, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xf6:
-    cpu_z80_set(self, 6, self->regs.word.hl);
+    cpu_z80_set(self, 6, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xf7:
-    cpu_z80_set(self, 6, CPU_Z80_EA_A);
+    cpu_z80_set(self, 6, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   case 0xf8:
-    cpu_z80_set(self, 7, CPU_Z80_EA_B);
+    cpu_z80_set(self, 7, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
     break;
   case 0xf9:
-    cpu_z80_set(self, 7, CPU_Z80_EA_C);
+    cpu_z80_set(self, 7, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
     break;
   case 0xfa:
-    cpu_z80_set(self, 7, CPU_Z80_EA_D);
+    cpu_z80_set(self, 7, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
     break;
   case 0xfb:
-    cpu_z80_set(self, 7, CPU_Z80_EA_E);
+    cpu_z80_set(self, 7, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
     break;
   case 0xfc:
-    cpu_z80_set(self, 7, CPU_Z80_EA_H);
+    cpu_z80_set(self, 7, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
     break;
   case 0xfd:
-    cpu_z80_set(self, 7, CPU_Z80_EA_L);
+    cpu_z80_set(self, 7, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
     break;
   case 0xfe:
-    cpu_z80_set(self, 7, self->regs.word.hl);
+    cpu_z80_set(self, 7, self->regs.word.hl, CPU_Z80_EA_NONE);
     break;
   case 0xff:
-    cpu_z80_set(self, 7, CPU_Z80_EA_A);
+    cpu_z80_set(self, 7, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
     break;
   }
 }
@@ -2182,7 +2182,7 @@ void cpu_z80_execute_dd(struct cpu_z80 *self) {
     cpu_z80_jp(self, self->regs.bit.zf, cpu_z80_fetch_word(self));
     break;
   case 0xcb:
-    cpu_z80_ill(self);
+    cpu_z80_execute_dd_cb(self);
     break;
   case 0xcc:
     cpu_z80_call(self, self->regs.bit.zf, cpu_z80_fetch_word(self));
@@ -2345,1553 +2345,3102 @@ void cpu_z80_execute_dd(struct cpu_z80 *self) {
   }
 }
 
-void cpu_z80_execute_ed(struct cpu_z80 *self) {
+void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
+  int ea = cpu_z80_displacement(self, self->regs.word.ix);
   switch (cpu_z80_fetch_byte(self)) {
   case 0x00:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_B);
     break;
   case 0x01:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_C);
     break;
   case 0x02:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_D);
     break;
   case 0x03:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_E);
     break;
   case 0x04:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_H);
     break;
   case 0x05:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x06:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x07:
-    cpu_z80_ill(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_A);
     break;
   case 0x08:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_B);
     break;
   case 0x09:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_C);
     break;
   case 0x0a:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_D);
     break;
   case 0x0b:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_E);
     break;
   case 0x0c:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_H);
     break;
   case 0x0d:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x0e:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x0f:
-    cpu_z80_ill(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_A);
     break;
   case 0x10:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_B);
     break;
   case 0x11:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_C);
     break;
   case 0x12:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_D);
     break;
   case 0x13:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_E);
     break;
   case 0x14:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_H);
     break;
   case 0x15:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x16:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x17:
-    cpu_z80_ill(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_A);
     break;
   case 0x18:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_B);
     break;
   case 0x19:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_C);
     break;
   case 0x1a:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_D);
     break;
   case 0x1b:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_E);
     break;
   case 0x1c:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_H);
     break;
   case 0x1d:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_L);
     break;
   case 0x1e:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x1f:
-    cpu_z80_ill(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_A);
     break;
   case 0x20:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_B);
     break;
   case 0x21:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_C);
     break;
   case 0x22:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_D);
     break;
   case 0x23:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_E);
     break;
   case 0x24:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_H);
     break;
   case 0x25:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_L);
     break;
   case 0x26:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x27:
-    cpu_z80_ill(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_A);
     break;
   case 0x28:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_B);
     break;
   case 0x29:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_C);
     break;
   case 0x2a:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_D);
     break;
   case 0x2b:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_E);
     break;
   case 0x2c:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_H);
     break;
   case 0x2d:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_L);
     break;
   case 0x2e:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x2f:
-    cpu_z80_ill(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_A);
     break;
   case 0x30:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_B);
     break;
   case 0x31:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_C);
     break;
   case 0x32:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_D);
     break;
   case 0x33:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_E);
     break;
   case 0x34:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_H);
     break;
   case 0x35:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_L);
     break;
   case 0x36:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x37:
-    cpu_z80_ill(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_A);
     break;
   case 0x38:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_B);
     break;
   case 0x39:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_C);
     break;
   case 0x3a:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_D);
     break;
   case 0x3b:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_E);
     break;
   case 0x3c:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_H);
     break;
   case 0x3d:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x3e:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x3f:
-    cpu_z80_ill(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_A);
     break;
   case 0x40:
-    cpu_z80_in(self, CPU_Z80_EA_B, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x41:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.b);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x42:
-    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.bc);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x43:
-    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.bc);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x44:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x45:
-    cpu_z80_retn(self);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x46:
-    cpu_z80_im(self, 0);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x47:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_I, self->regs.byte.a);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x48:
-    cpu_z80_in(self, CPU_Z80_EA_C, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x49:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.c);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4a:
-    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.bc);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4b:
-    cpu_z80_ld_word(self, CPU_Z80_EA_BC, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4c:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4d:
-    cpu_z80_reti(self);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4e:
-    cpu_z80_im(self, 0);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4f:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_R, self->regs.byte.a);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x50:
-    cpu_z80_in(self, CPU_Z80_EA_D, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x51:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.d);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x52:
-    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.de);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x53:
-    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.de);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x54:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x55:
-    cpu_z80_retn(self);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x56:
-    cpu_z80_im(self, 1);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x57:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.i);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x58:
-    cpu_z80_in(self, CPU_Z80_EA_E, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x59:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.e);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5a:
-    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.de);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5b:
-    cpu_z80_ld_word(self, CPU_Z80_EA_DE, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5c:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5d:
-    cpu_z80_reti(self);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5e:
-    cpu_z80_im(self, 2);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5f:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.r);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x60:
-    cpu_z80_in(self, CPU_Z80_EA_H, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x61:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.h);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x62:
-    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.hl);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x63:
-    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.hl);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x64:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x65:
-    cpu_z80_retn(self);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x66:
-    cpu_z80_im(self, 0);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x67:
-    cpu_z80_rrd(self);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x68:
-    cpu_z80_in(self, CPU_Z80_EA_L, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x69:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.l);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6a:
-    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.hl);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6b:
-    cpu_z80_ld_word(self, CPU_Z80_EA_HL, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6c:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6d:
-    cpu_z80_reti(self);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6e:
-    cpu_z80_im(self, 0);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6f:
-    cpu_z80_rld(self);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x70:
-    cpu_z80_in(self, CPU_Z80_EA_NONE, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x71:
-    cpu_z80_out(self, self->regs.word.bc, 0);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x72:
-    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.sp);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x73:
-    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.sp);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x74:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x75:
-    cpu_z80_retn(self);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x76:
-    cpu_z80_im(self, 1);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x77:
-    cpu_z80_nop(self);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x78:
-    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x79:
-    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.a);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7a:
-    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.sp);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7b:
-    cpu_z80_ld_word(self, CPU_Z80_EA_SP, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7c:
-    cpu_z80_neg(self);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7d:
-    cpu_z80_reti(self);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7e:
-    cpu_z80_im(self, 2);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7f:
-    cpu_z80_nop(self);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x80:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_B);
     break;
   case 0x81:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_C);
     break;
   case 0x82:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_D);
     break;
   case 0x83:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_E);
     break;
   case 0x84:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_H);
     break;
   case 0x85:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0x86:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_NONE);
     break;
   case 0x87:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_A);
     break;
   case 0x88:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_B);
     break;
   case 0x89:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_C);
     break;
   case 0x8a:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_D);
     break;
   case 0x8b:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_E);
     break;
   case 0x8c:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_H);
     break;
   case 0x8d:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0x8e:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_NONE);
     break;
   case 0x8f:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_A);
     break;
   case 0x90:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_B);
     break;
   case 0x91:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_C);
     break;
   case 0x92:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_D);
     break;
   case 0x93:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_E);
     break;
   case 0x94:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_H);
     break;
   case 0x95:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0x96:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_NONE);
     break;
   case 0x97:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_A);
     break;
   case 0x98:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_B);
     break;
   case 0x99:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_C);
     break;
   case 0x9a:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_D);
     break;
   case 0x9b:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_E);
     break;
   case 0x9c:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_H);
     break;
   case 0x9d:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0x9e:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_NONE);
     break;
   case 0x9f:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_A);
     break;
   case 0xa0:
-    cpu_z80_ldi(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_B);
     break;
   case 0xa1:
-    cpu_z80_cpi(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_C);
     break;
   case 0xa2:
-    cpu_z80_ini(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_D);
     break;
   case 0xa3:
-    cpu_z80_outi(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_E);
     break;
   case 0xa4:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_H);
     break;
   case 0xa5:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xa6:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_NONE);
     break;
   case 0xa7:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_A);
     break;
   case 0xa8:
-    cpu_z80_ldd(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_B);
     break;
   case 0xa9:
-    cpu_z80_cpd(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_C);
     break;
   case 0xaa:
-    cpu_z80_ind(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_D);
     break;
   case 0xab:
-    cpu_z80_outd(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_E);
     break;
   case 0xac:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_H);
     break;
   case 0xad:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xae:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_NONE);
     break;
   case 0xaf:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_A);
     break;
   case 0xb0:
-    cpu_z80_ldir(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_B);
     break;
   case 0xb1:
-    cpu_z80_cpir(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_C);
     break;
   case 0xb2:
-    cpu_z80_inir(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_D);
     break;
   case 0xb3:
-    cpu_z80_otir(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_E);
     break;
   case 0xb4:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_H);
     break;
   case 0xb5:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xb6:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_NONE);
     break;
   case 0xb7:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_A);
     break;
   case 0xb8:
-    cpu_z80_lddr(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_B);
     break;
   case 0xb9:
-    cpu_z80_cpdr(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_C);
     break;
   case 0xba:
-    cpu_z80_indr(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_D);
     break;
   case 0xbb:
-    cpu_z80_otdr(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_E);
     break;
   case 0xbc:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_H);
     break;
   case 0xbd:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xbe:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_NONE);
     break;
   case 0xbf:
-    cpu_z80_ill(self);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_A);
     break;
   case 0xc0:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_B);
     break;
   case 0xc1:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_C);
     break;
   case 0xc2:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_D);
     break;
   case 0xc3:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_E);
     break;
   case 0xc4:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_H);
     break;
   case 0xc5:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0xc6:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_NONE);
     break;
   case 0xc7:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_A);
     break;
   case 0xc8:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_B);
     break;
   case 0xc9:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_C);
     break;
   case 0xca:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_D);
     break;
   case 0xcb:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_E);
     break;
   case 0xcc:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_H);
     break;
   case 0xcd:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0xce:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_NONE);
     break;
   case 0xcf:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_A);
     break;
   case 0xd0:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_B);
     break;
   case 0xd1:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_C);
     break;
   case 0xd2:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_D);
     break;
   case 0xd3:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_E);
     break;
   case 0xd4:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_H);
     break;
   case 0xd5:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0xd6:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_NONE);
     break;
   case 0xd7:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_A);
     break;
   case 0xd8:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_B);
     break;
   case 0xd9:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_C);
     break;
   case 0xda:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_D);
     break;
   case 0xdb:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_E);
     break;
   case 0xdc:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_H);
     break;
   case 0xdd:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0xde:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_NONE);
     break;
   case 0xdf:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_A);
     break;
   case 0xe0:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_B);
     break;
   case 0xe1:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_C);
     break;
   case 0xe2:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_D);
     break;
   case 0xe3:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_E);
     break;
   case 0xe4:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_H);
     break;
   case 0xe5:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xe6:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_NONE);
     break;
   case 0xe7:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_A);
     break;
   case 0xe8:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_B);
     break;
   case 0xe9:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_C);
     break;
   case 0xea:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_D);
     break;
   case 0xeb:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_E);
     break;
   case 0xec:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_H);
     break;
   case 0xed:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xee:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_NONE);
     break;
   case 0xef:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_A);
     break;
   case 0xf0:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_B);
     break;
   case 0xf1:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_C);
     break;
   case 0xf2:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_D);
     break;
   case 0xf3:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_E);
     break;
   case 0xf4:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_H);
     break;
   case 0xf5:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xf6:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_NONE);
     break;
   case 0xf7:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_A);
     break;
   case 0xf8:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_B);
     break;
   case 0xf9:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_C);
     break;
   case 0xfa:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_D);
     break;
   case 0xfb:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_E);
     break;
   case 0xfc:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_H);
     break;
   case 0xfd:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xfe:
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_NONE);
+    break;
+  case 0xff:
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_A);
+    break;
+  }
+}
+
+void cpu_z80_execute_ed(struct cpu_z80 *self) {
+  switch (cpu_z80_fetch_byte(self)) {
+  case 0x00:
+    cpu_z80_ill(self);
+    break;
+  case 0x01:
+    cpu_z80_ill(self);
+    break;
+  case 0x02:
+    cpu_z80_ill(self);
+    break;
+  case 0x03:
+    cpu_z80_ill(self);
+    break;
+  case 0x04:
+    cpu_z80_ill(self);
+    break;
+  case 0x05:
+    cpu_z80_ill(self);
+    break;
+  case 0x06:
+    cpu_z80_ill(self);
+    break;
+  case 0x07:
+    cpu_z80_ill(self);
+    break;
+  case 0x08:
+    cpu_z80_ill(self);
+    break;
+  case 0x09:
+    cpu_z80_ill(self);
+    break;
+  case 0x0a:
+    cpu_z80_ill(self);
+    break;
+  case 0x0b:
+    cpu_z80_ill(self);
+    break;
+  case 0x0c:
+    cpu_z80_ill(self);
+    break;
+  case 0x0d:
+    cpu_z80_ill(self);
+    break;
+  case 0x0e:
+    cpu_z80_ill(self);
+    break;
+  case 0x0f:
+    cpu_z80_ill(self);
+    break;
+  case 0x10:
+    cpu_z80_ill(self);
+    break;
+  case 0x11:
+    cpu_z80_ill(self);
+    break;
+  case 0x12:
+    cpu_z80_ill(self);
+    break;
+  case 0x13:
+    cpu_z80_ill(self);
+    break;
+  case 0x14:
+    cpu_z80_ill(self);
+    break;
+  case 0x15:
+    cpu_z80_ill(self);
+    break;
+  case 0x16:
+    cpu_z80_ill(self);
+    break;
+  case 0x17:
+    cpu_z80_ill(self);
+    break;
+  case 0x18:
+    cpu_z80_ill(self);
+    break;
+  case 0x19:
+    cpu_z80_ill(self);
+    break;
+  case 0x1a:
+    cpu_z80_ill(self);
+    break;
+  case 0x1b:
+    cpu_z80_ill(self);
+    break;
+  case 0x1c:
+    cpu_z80_ill(self);
+    break;
+  case 0x1d:
+    cpu_z80_ill(self);
+    break;
+  case 0x1e:
+    cpu_z80_ill(self);
+    break;
+  case 0x1f:
+    cpu_z80_ill(self);
+    break;
+  case 0x20:
+    cpu_z80_ill(self);
+    break;
+  case 0x21:
+    cpu_z80_ill(self);
+    break;
+  case 0x22:
+    cpu_z80_ill(self);
+    break;
+  case 0x23:
+    cpu_z80_ill(self);
+    break;
+  case 0x24:
+    cpu_z80_ill(self);
+    break;
+  case 0x25:
+    cpu_z80_ill(self);
+    break;
+  case 0x26:
+    cpu_z80_ill(self);
+    break;
+  case 0x27:
+    cpu_z80_ill(self);
+    break;
+  case 0x28:
+    cpu_z80_ill(self);
+    break;
+  case 0x29:
+    cpu_z80_ill(self);
+    break;
+  case 0x2a:
+    cpu_z80_ill(self);
+    break;
+  case 0x2b:
+    cpu_z80_ill(self);
+    break;
+  case 0x2c:
+    cpu_z80_ill(self);
+    break;
+  case 0x2d:
+    cpu_z80_ill(self);
+    break;
+  case 0x2e:
+    cpu_z80_ill(self);
+    break;
+  case 0x2f:
+    cpu_z80_ill(self);
+    break;
+  case 0x30:
+    cpu_z80_ill(self);
+    break;
+  case 0x31:
+    cpu_z80_ill(self);
+    break;
+  case 0x32:
+    cpu_z80_ill(self);
+    break;
+  case 0x33:
+    cpu_z80_ill(self);
+    break;
+  case 0x34:
+    cpu_z80_ill(self);
+    break;
+  case 0x35:
+    cpu_z80_ill(self);
+    break;
+  case 0x36:
+    cpu_z80_ill(self);
+    break;
+  case 0x37:
+    cpu_z80_ill(self);
+    break;
+  case 0x38:
+    cpu_z80_ill(self);
+    break;
+  case 0x39:
+    cpu_z80_ill(self);
+    break;
+  case 0x3a:
+    cpu_z80_ill(self);
+    break;
+  case 0x3b:
+    cpu_z80_ill(self);
+    break;
+  case 0x3c:
+    cpu_z80_ill(self);
+    break;
+  case 0x3d:
+    cpu_z80_ill(self);
+    break;
+  case 0x3e:
+    cpu_z80_ill(self);
+    break;
+  case 0x3f:
+    cpu_z80_ill(self);
+    break;
+  case 0x40:
+    cpu_z80_in(self, CPU_Z80_EA_B, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x41:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.b);
+    break;
+  case 0x42:
+    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.bc);
+    break;
+  case 0x43:
+    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.bc);
+    break;
+  case 0x44:
+    cpu_z80_neg(self);
+    break;
+  case 0x45:
+    cpu_z80_retn(self);
+    break;
+  case 0x46:
+    cpu_z80_im(self, 0);
+    break;
+  case 0x47:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_I, self->regs.byte.a);
+    break;
+  case 0x48:
+    cpu_z80_in(self, CPU_Z80_EA_C, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x49:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.c);
+    break;
+  case 0x4a:
+    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.bc);
+    break;
+  case 0x4b:
+    cpu_z80_ld_word(self, CPU_Z80_EA_BC, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    break;
+  case 0x4c:
+    cpu_z80_neg(self);
+    break;
+  case 0x4d:
+    cpu_z80_reti(self);
+    break;
+  case 0x4e:
+    cpu_z80_im(self, 0);
+    break;
+  case 0x4f:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_R, self->regs.byte.a);
+    break;
+  case 0x50:
+    cpu_z80_in(self, CPU_Z80_EA_D, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x51:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.d);
+    break;
+  case 0x52:
+    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.de);
+    break;
+  case 0x53:
+    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.de);
+    break;
+  case 0x54:
+    cpu_z80_neg(self);
+    break;
+  case 0x55:
+    cpu_z80_retn(self);
+    break;
+  case 0x56:
+    cpu_z80_im(self, 1);
+    break;
+  case 0x57:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.i);
+    break;
+  case 0x58:
+    cpu_z80_in(self, CPU_Z80_EA_E, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x59:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.e);
+    break;
+  case 0x5a:
+    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.de);
+    break;
+  case 0x5b:
+    cpu_z80_ld_word(self, CPU_Z80_EA_DE, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    break;
+  case 0x5c:
+    cpu_z80_neg(self);
+    break;
+  case 0x5d:
+    cpu_z80_reti(self);
+    break;
+  case 0x5e:
+    cpu_z80_im(self, 2);
+    break;
+  case 0x5f:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.r);
+    break;
+  case 0x60:
+    cpu_z80_in(self, CPU_Z80_EA_H, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x61:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.h);
+    break;
+  case 0x62:
+    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.hl);
+    break;
+  case 0x63:
+    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.hl);
+    break;
+  case 0x64:
+    cpu_z80_neg(self);
+    break;
+  case 0x65:
+    cpu_z80_retn(self);
+    break;
+  case 0x66:
+    cpu_z80_im(self, 0);
+    break;
+  case 0x67:
+    cpu_z80_rrd(self);
+    break;
+  case 0x68:
+    cpu_z80_in(self, CPU_Z80_EA_L, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x69:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.l);
+    break;
+  case 0x6a:
+    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.hl);
+    break;
+  case 0x6b:
+    cpu_z80_ld_word(self, CPU_Z80_EA_HL, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    break;
+  case 0x6c:
+    cpu_z80_neg(self);
+    break;
+  case 0x6d:
+    cpu_z80_reti(self);
+    break;
+  case 0x6e:
+    cpu_z80_im(self, 0);
+    break;
+  case 0x6f:
+    cpu_z80_rld(self);
+    break;
+  case 0x70:
+    cpu_z80_in(self, CPU_Z80_EA_NONE, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x71:
+    cpu_z80_out(self, self->regs.word.bc, 0);
+    break;
+  case 0x72:
+    cpu_z80_sbc_word(self, CPU_Z80_EA_HL, self->regs.word.sp);
+    break;
+  case 0x73:
+    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.sp);
+    break;
+  case 0x74:
+    cpu_z80_neg(self);
+    break;
+  case 0x75:
+    cpu_z80_retn(self);
+    break;
+  case 0x76:
+    cpu_z80_im(self, 1);
+    break;
+  case 0x77:
+    cpu_z80_nop(self);
+    break;
+  case 0x78:
+    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, self->regs.word.bc));
+    break;
+  case 0x79:
+    cpu_z80_out(self, self->regs.word.bc, self->regs.byte.a);
+    break;
+  case 0x7a:
+    cpu_z80_adc_word(self, CPU_Z80_EA_HL, self->regs.word.sp);
+    break;
+  case 0x7b:
+    cpu_z80_ld_word(self, CPU_Z80_EA_SP, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    break;
+  case 0x7c:
+    cpu_z80_neg(self);
+    break;
+  case 0x7d:
+    cpu_z80_reti(self);
+    break;
+  case 0x7e:
+    cpu_z80_im(self, 2);
+    break;
+  case 0x7f:
+    cpu_z80_nop(self);
+    break;
+  case 0x80:
+    cpu_z80_ill(self);
+    break;
+  case 0x81:
+    cpu_z80_ill(self);
+    break;
+  case 0x82:
+    cpu_z80_ill(self);
+    break;
+  case 0x83:
+    cpu_z80_ill(self);
+    break;
+  case 0x84:
+    cpu_z80_ill(self);
+    break;
+  case 0x85:
+    cpu_z80_ill(self);
+    break;
+  case 0x86:
+    cpu_z80_ill(self);
+    break;
+  case 0x87:
+    cpu_z80_ill(self);
+    break;
+  case 0x88:
+    cpu_z80_ill(self);
+    break;
+  case 0x89:
+    cpu_z80_ill(self);
+    break;
+  case 0x8a:
+    cpu_z80_ill(self);
+    break;
+  case 0x8b:
+    cpu_z80_ill(self);
+    break;
+  case 0x8c:
+    cpu_z80_ill(self);
+    break;
+  case 0x8d:
+    cpu_z80_ill(self);
+    break;
+  case 0x8e:
+    cpu_z80_ill(self);
+    break;
+  case 0x8f:
+    cpu_z80_ill(self);
+    break;
+  case 0x90:
+    cpu_z80_ill(self);
+    break;
+  case 0x91:
+    cpu_z80_ill(self);
+    break;
+  case 0x92:
+    cpu_z80_ill(self);
+    break;
+  case 0x93:
+    cpu_z80_ill(self);
+    break;
+  case 0x94:
+    cpu_z80_ill(self);
+    break;
+  case 0x95:
+    cpu_z80_ill(self);
+    break;
+  case 0x96:
+    cpu_z80_ill(self);
+    break;
+  case 0x97:
+    cpu_z80_ill(self);
+    break;
+  case 0x98:
+    cpu_z80_ill(self);
+    break;
+  case 0x99:
+    cpu_z80_ill(self);
+    break;
+  case 0x9a:
+    cpu_z80_ill(self);
+    break;
+  case 0x9b:
+    cpu_z80_ill(self);
+    break;
+  case 0x9c:
+    cpu_z80_ill(self);
+    break;
+  case 0x9d:
+    cpu_z80_ill(self);
+    break;
+  case 0x9e:
+    cpu_z80_ill(self);
+    break;
+  case 0x9f:
+    cpu_z80_ill(self);
+    break;
+  case 0xa0:
+    cpu_z80_ldi(self);
+    break;
+  case 0xa1:
+    cpu_z80_cpi(self);
+    break;
+  case 0xa2:
+    cpu_z80_ini(self);
+    break;
+  case 0xa3:
+    cpu_z80_outi(self);
+    break;
+  case 0xa4:
+    cpu_z80_ill(self);
+    break;
+  case 0xa5:
+    cpu_z80_ill(self);
+    break;
+  case 0xa6:
+    cpu_z80_ill(self);
+    break;
+  case 0xa7:
+    cpu_z80_ill(self);
+    break;
+  case 0xa8:
+    cpu_z80_ldd(self);
+    break;
+  case 0xa9:
+    cpu_z80_cpd(self);
+    break;
+  case 0xaa:
+    cpu_z80_ind(self);
+    break;
+  case 0xab:
+    cpu_z80_outd(self);
+    break;
+  case 0xac:
+    cpu_z80_ill(self);
+    break;
+  case 0xad:
+    cpu_z80_ill(self);
+    break;
+  case 0xae:
+    cpu_z80_ill(self);
+    break;
+  case 0xaf:
+    cpu_z80_ill(self);
+    break;
+  case 0xb0:
+    cpu_z80_ldir(self);
+    break;
+  case 0xb1:
+    cpu_z80_cpir(self);
+    break;
+  case 0xb2:
+    cpu_z80_inir(self);
+    break;
+  case 0xb3:
+    cpu_z80_otir(self);
+    break;
+  case 0xb4:
+    cpu_z80_ill(self);
+    break;
+  case 0xb5:
+    cpu_z80_ill(self);
+    break;
+  case 0xb6:
+    cpu_z80_ill(self);
+    break;
+  case 0xb7:
+    cpu_z80_ill(self);
+    break;
+  case 0xb8:
+    cpu_z80_lddr(self);
+    break;
+  case 0xb9:
+    cpu_z80_cpdr(self);
+    break;
+  case 0xba:
+    cpu_z80_indr(self);
+    break;
+  case 0xbb:
+    cpu_z80_otdr(self);
+    break;
+  case 0xbc:
+    cpu_z80_ill(self);
+    break;
+  case 0xbd:
+    cpu_z80_ill(self);
+    break;
+  case 0xbe:
+    cpu_z80_ill(self);
+    break;
+  case 0xbf:
+    cpu_z80_ill(self);
+    break;
+  case 0xc0:
+    cpu_z80_ill(self);
+    break;
+  case 0xc1:
+    cpu_z80_ill(self);
+    break;
+  case 0xc2:
+    cpu_z80_ill(self);
+    break;
+  case 0xc3:
+    cpu_z80_ill(self);
+    break;
+  case 0xc4:
+    cpu_z80_ill(self);
+    break;
+  case 0xc5:
+    cpu_z80_ill(self);
+    break;
+  case 0xc6:
+    cpu_z80_ill(self);
+    break;
+  case 0xc7:
+    cpu_z80_ill(self);
+    break;
+  case 0xc8:
+    cpu_z80_ill(self);
+    break;
+  case 0xc9:
+    cpu_z80_ill(self);
+    break;
+  case 0xca:
+    cpu_z80_ill(self);
+    break;
+  case 0xcb:
+    cpu_z80_ill(self);
+    break;
+  case 0xcc:
+    cpu_z80_ill(self);
+    break;
+  case 0xcd:
+    cpu_z80_ill(self);
+    break;
+  case 0xce:
+    cpu_z80_ill(self);
+    break;
+  case 0xcf:
+    cpu_z80_ill(self);
+    break;
+  case 0xd0:
+    cpu_z80_ill(self);
+    break;
+  case 0xd1:
+    cpu_z80_ill(self);
+    break;
+  case 0xd2:
+    cpu_z80_ill(self);
+    break;
+  case 0xd3:
+    cpu_z80_ill(self);
+    break;
+  case 0xd4:
+    cpu_z80_ill(self);
+    break;
+  case 0xd5:
+    cpu_z80_ill(self);
+    break;
+  case 0xd6:
+    cpu_z80_ill(self);
+    break;
+  case 0xd7:
+    cpu_z80_ill(self);
+    break;
+  case 0xd8:
+    cpu_z80_ill(self);
+    break;
+  case 0xd9:
+    cpu_z80_ill(self);
+    break;
+  case 0xda:
+    cpu_z80_ill(self);
+    break;
+  case 0xdb:
+    cpu_z80_ill(self);
+    break;
+  case 0xdc:
+    cpu_z80_ill(self);
+    break;
+  case 0xdd:
+    cpu_z80_ill(self);
+    break;
+  case 0xde:
+    cpu_z80_ill(self);
+    break;
+  case 0xdf:
+    cpu_z80_ill(self);
+    break;
+  case 0xe0:
+    cpu_z80_ill(self);
+    break;
+  case 0xe1:
+    cpu_z80_ill(self);
+    break;
+  case 0xe2:
+    cpu_z80_ill(self);
+    break;
+  case 0xe3:
+    cpu_z80_ill(self);
+    break;
+  case 0xe4:
+    cpu_z80_ill(self);
+    break;
+  case 0xe5:
+    cpu_z80_ill(self);
+    break;
+  case 0xe6:
+    cpu_z80_ill(self);
+    break;
+  case 0xe7:
+    cpu_z80_ill(self);
+    break;
+  case 0xe8:
+    cpu_z80_ill(self);
+    break;
+  case 0xe9:
+    cpu_z80_ill(self);
+    break;
+  case 0xea:
+    cpu_z80_ill(self);
+    break;
+  case 0xeb:
+    cpu_z80_ill(self);
+    break;
+  case 0xec:
+    cpu_z80_ill(self);
+    break;
+  case 0xed:
+    cpu_z80_ill(self);
+    break;
+  case 0xee:
+    cpu_z80_ill(self);
+    break;
+  case 0xef:
+    cpu_z80_ill(self);
+    break;
+  case 0xf0:
+    cpu_z80_ill(self);
+    break;
+  case 0xf1:
+    cpu_z80_ill(self);
+    break;
+  case 0xf2:
+    cpu_z80_ill(self);
+    break;
+  case 0xf3:
+    cpu_z80_ill(self);
+    break;
+  case 0xf4:
+    cpu_z80_ill(self);
+    break;
+  case 0xf5:
+    cpu_z80_ill(self);
+    break;
+  case 0xf6:
+    cpu_z80_ill(self);
+    break;
+  case 0xf7:
+    cpu_z80_ill(self);
+    break;
+  case 0xf8:
+    cpu_z80_ill(self);
+    break;
+  case 0xf9:
+    cpu_z80_ill(self);
+    break;
+  case 0xfa:
+    cpu_z80_ill(self);
+    break;
+  case 0xfb:
+    cpu_z80_ill(self);
+    break;
+  case 0xfc:
+    cpu_z80_ill(self);
+    break;
+  case 0xfd:
+    cpu_z80_ill(self);
+    break;
+  case 0xfe:
+    cpu_z80_ill(self);
+    break;
+  case 0xff:
+    cpu_z80_ill(self);
+    break;
+  }
+}
+
+void cpu_z80_execute_fd(struct cpu_z80 *self) {
+  switch (cpu_z80_fetch_byte(self)) {
+  case 0x00:
+    cpu_z80_nop(self);
+    break;
+  case 0x01:
+    cpu_z80_ld_word(self, CPU_Z80_EA_BC, cpu_z80_fetch_word(self));
+    break;
+  case 0x02:
+    cpu_z80_ld_byte(self, self->regs.word.bc, self->regs.byte.a);
+    break;
+  case 0x03:
+    cpu_z80_inc_word(self, CPU_Z80_EA_BC);
+    break;
+  case 0x04:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_B);
+    break;
+  case 0x05:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_B);
+    break;
+  case 0x06:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, cpu_z80_fetch_byte(self));
+    break;
+  case 0x07:
+    cpu_z80_rlca(self);
+    break;
+  case 0x08:
+    cpu_z80_ex(self, CPU_Z80_EA_AF, CPU_Z80_EA_AF_PRIME);
+    break;
+  case 0x09:
+    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.bc);
+    break;
+  case 0x0a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, self->regs.word.bc));
+    break;
+  case 0x0b:
+    cpu_z80_dec_word(self, CPU_Z80_EA_BC);
+    break;
+  case 0x0c:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_C);
+    break;
+  case 0x0d:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_C);
+    break;
+  case 0x0e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, cpu_z80_fetch_byte(self));
+    break;
+  case 0x0f:
+    cpu_z80_rrca(self);
+    break;
+  case 0x10:
+    cpu_z80_djnz(self, cpu_z80_relative(self));
+    break;
+  case 0x11:
+    cpu_z80_ld_word(self, CPU_Z80_EA_DE, cpu_z80_fetch_word(self));
+    break;
+  case 0x12:
+    cpu_z80_ld_byte(self, self->regs.word.de, self->regs.byte.a);
+    break;
+  case 0x13:
+    cpu_z80_inc_word(self, CPU_Z80_EA_DE);
+    break;
+  case 0x14:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_D);
+    break;
+  case 0x15:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_D);
+    break;
+  case 0x16:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, cpu_z80_fetch_byte(self));
+    break;
+  case 0x17:
+    cpu_z80_rla(self);
+    break;
+  case 0x18:
+    cpu_z80_jr(self, true, cpu_z80_relative(self));
+    break;
+  case 0x19:
+    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.de);
+    break;
+  case 0x1a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, self->regs.word.de));
+    break;
+  case 0x1b:
+    cpu_z80_dec_word(self, CPU_Z80_EA_DE);
+    break;
+  case 0x1c:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_E);
+    break;
+  case 0x1d:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_E);
+    break;
+  case 0x1e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, cpu_z80_fetch_byte(self));
+    break;
+  case 0x1f:
+    cpu_z80_rra(self);
+    break;
+  case 0x20:
+    cpu_z80_jr(self, !self->regs.bit.zf, cpu_z80_relative(self));
+    break;
+  case 0x21:
+    cpu_z80_ld_word(self, CPU_Z80_EA_IY, cpu_z80_fetch_word(self));
+    break;
+  case 0x22:
+    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.iy);
+    break;
+  case 0x23:
+    cpu_z80_inc_word(self, CPU_Z80_EA_IY);
+    break;
+  case 0x24:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_IYH);
+    break;
+  case 0x25:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_IYH);
+    break;
+  case 0x26:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, cpu_z80_fetch_byte(self));
+    break;
+  case 0x27:
+    cpu_z80_daa(self);
+    break;
+  case 0x28:
+    cpu_z80_jr(self, self->regs.bit.zf, cpu_z80_relative(self));
+    break;
+  case 0x29:
+    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.iy);
+    break;
+  case 0x2a:
+    cpu_z80_ld_word(self, CPU_Z80_EA_IY, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    break;
+  case 0x2b:
+    cpu_z80_dec_word(self, CPU_Z80_EA_IY);
+    break;
+  case 0x2c:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_IYL);
+    break;
+  case 0x2d:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_IYL);
+    break;
+  case 0x2e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, cpu_z80_fetch_byte(self));
+    break;
+  case 0x2f:
+    cpu_z80_cpl(self);
+    break;
+  case 0x30:
+    cpu_z80_jr(self, !self->regs.bit.cf, cpu_z80_relative(self));
+    break;
+  case 0x31:
+    cpu_z80_ld_word(self, CPU_Z80_EA_SP, cpu_z80_fetch_word(self));
+    break;
+  case 0x32:
+    cpu_z80_ld_byte(self, cpu_z80_fetch_word(self), self->regs.byte.a);
+    break;
+  case 0x33:
+    cpu_z80_inc_word(self, CPU_Z80_EA_SP);
+    break;
+  case 0x34:
+    cpu_z80_inc_byte(self, cpu_z80_displacement(self, self->regs.word.iy));
+    break;
+  case 0x35:
+    cpu_z80_dec_byte(self, cpu_z80_displacement(self, self->regs.word.iy));
+    break;
+  case 0x36:
+    {
+      int ea = cpu_z80_displacement(self, self->regs.word.iy);
+      cpu_z80_ld_byte(self, ea, cpu_z80_fetch_byte(self));
+    }
+    break;
+  case 0x37:
+    cpu_z80_scf(self);
+    break;
+  case 0x38:
+    cpu_z80_jr(self, self->regs.bit.cf, cpu_z80_relative(self));
+    break;
+  case 0x39:
+    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.sp);
+    break;
+  case 0x3a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_fetch_word(self)));
+    break;
+  case 0x3b:
+    cpu_z80_dec_word(self, CPU_Z80_EA_SP);
+    break;
+  case 0x3c:
+    cpu_z80_inc_byte(self, CPU_Z80_EA_A);
+    break;
+  case 0x3d:
+    cpu_z80_dec_byte(self, CPU_Z80_EA_A);
+    break;
+  case 0x3e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    break;
+  case 0x3f:
+    cpu_z80_ccf(self);
+    break;
+  case 0x40:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.b);
+    break;
+  case 0x41:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.c);
+    break;
+  case 0x42:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.d);
+    break;
+  case 0x43:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.e);
+    break;
+  case 0x44:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.iyh);
+    break;
+  case 0x45:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.iyl);
+    break;
+  case 0x46:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x47:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.a);
+    break;
+  case 0x48:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.b);
+    break;
+  case 0x49:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.c);
+    break;
+  case 0x4a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.d);
+    break;
+  case 0x4b:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.e);
+    break;
+  case 0x4c:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.iyh);
+    break;
+  case 0x4d:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.iyl);
+    break;
+  case 0x4e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x4f:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.a);
+    break;
+  case 0x50:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.b);
+    break;
+  case 0x51:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.c);
+    break;
+  case 0x52:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.d);
+    break;
+  case 0x53:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.e);
+    break;
+  case 0x54:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.iyh);
+    break;
+  case 0x55:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.iyl);
+    break;
+  case 0x56:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x57:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.a);
+    break;
+  case 0x58:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.b);
+    break;
+  case 0x59:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.c);
+    break;
+  case 0x5a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.d);
+    break;
+  case 0x5b:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.e);
+    break;
+  case 0x5c:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.iyh);
+    break;
+  case 0x5d:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.iyl);
+    break;
+  case 0x5e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x5f:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.a);
+    break;
+  case 0x60:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.b);
+    break;
+  case 0x61:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.c);
+    break;
+  case 0x62:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.d);
+    break;
+  case 0x63:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.e);
+    break;
+  case 0x64:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.iyh);
+    break;
+  case 0x65:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.iyl);
+    break;
+  case 0x66:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_H, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x67:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.a);
+    break;
+  case 0x68:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.b);
+    break;
+  case 0x69:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.c);
+    break;
+  case 0x6a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.d);
+    break;
+  case 0x6b:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.e);
+    break;
+  case 0x6c:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.iyh);
+    break;
+  case 0x6d:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.iyl);
+    break;
+  case 0x6e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_L, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x6f:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.a);
+    break;
+  case 0x70:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.b);
+    break;
+  case 0x71:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.c);
+    break;
+  case 0x72:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.d);
+    break;
+  case 0x73:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.e);
+    break;
+  case 0x74:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.h);
+    break;
+  case 0x75:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.l);
+    break;
+  case 0x76:
+    cpu_z80_halt(self);
+    break;
+  case 0x77:
+    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.a);
+    break;
+  case 0x78:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    break;
+  case 0x79:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    break;
+  case 0x7a:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    break;
+  case 0x7b:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    break;
+  case 0x7c:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    break;
+  case 0x7d:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    break;
+  case 0x7e:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x7f:
+    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    break;
+  case 0x80:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    break;
+  case 0x81:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    break;
+  case 0x82:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    break;
+  case 0x83:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    break;
+  case 0x84:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    break;
+  case 0x85:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    break;
+  case 0x86:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x87:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    break;
+  case 0x88:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    break;
+  case 0x89:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    break;
+  case 0x8a:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    break;
+  case 0x8b:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    break;
+  case 0x8c:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    break;
+  case 0x8d:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    break;
+  case 0x8e:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x8f:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    break;
+  case 0x90:
+    cpu_z80_sub(self, self->regs.byte.b);
+    break;
+  case 0x91:
+    cpu_z80_sub(self, self->regs.byte.c);
+    break;
+  case 0x92:
+    cpu_z80_sub(self, self->regs.byte.d);
+    break;
+  case 0x93:
+    cpu_z80_sub(self, self->regs.byte.e);
+    break;
+  case 0x94:
+    cpu_z80_sub(self, self->regs.byte.iyh);
+    break;
+  case 0x95:
+    cpu_z80_sub(self, self->regs.byte.iyl);
+    break;
+  case 0x96:
+    cpu_z80_sub(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x97:
+    cpu_z80_sub(self, self->regs.byte.a);
+    break;
+  case 0x98:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    break;
+  case 0x99:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    break;
+  case 0x9a:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    break;
+  case 0x9b:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    break;
+  case 0x9c:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    break;
+  case 0x9d:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    break;
+  case 0x9e:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0x9f:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    break;
+  case 0xa0:
+    cpu_z80_and(self, self->regs.byte.b);
+    break;
+  case 0xa1:
+    cpu_z80_and(self, self->regs.byte.c);
+    break;
+  case 0xa2:
+    cpu_z80_and(self, self->regs.byte.d);
+    break;
+  case 0xa3:
+    cpu_z80_and(self, self->regs.byte.e);
+    break;
+  case 0xa4:
+    cpu_z80_and(self, self->regs.byte.iyh);
+    break;
+  case 0xa5:
+    cpu_z80_and(self, self->regs.byte.iyl);
+    break;
+  case 0xa6:
+    cpu_z80_and(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0xa7:
+    cpu_z80_and(self, self->regs.byte.a);
+    break;
+  case 0xa8:
+    cpu_z80_xor(self, self->regs.byte.b);
+    break;
+  case 0xa9:
+    cpu_z80_xor(self, self->regs.byte.c);
+    break;
+  case 0xaa:
+    cpu_z80_xor(self, self->regs.byte.d);
+    break;
+  case 0xab:
+    cpu_z80_xor(self, self->regs.byte.e);
+    break;
+  case 0xac:
+    cpu_z80_xor(self, self->regs.byte.iyh);
+    break;
+  case 0xad:
+    cpu_z80_xor(self, self->regs.byte.iyl);
+    break;
+  case 0xae:
+    cpu_z80_xor(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0xaf:
+    cpu_z80_xor(self, self->regs.byte.a);
+    break;
+  case 0xb0:
+    cpu_z80_or(self, self->regs.byte.b);
+    break;
+  case 0xb1:
+    cpu_z80_or(self, self->regs.byte.c);
+    break;
+  case 0xb2:
+    cpu_z80_or(self, self->regs.byte.d);
+    break;
+  case 0xb3:
+    cpu_z80_or(self, self->regs.byte.e);
+    break;
+  case 0xb4:
+    cpu_z80_or(self, self->regs.byte.iyh);
+    break;
+  case 0xb5:
+    cpu_z80_or(self, self->regs.byte.iyl);
+    break;
+  case 0xb6:
+    cpu_z80_or(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0xb7:
+    cpu_z80_or(self, self->regs.byte.a);
+    break;
+  case 0xb8:
+    cpu_z80_cp(self, self->regs.byte.b);
+    break;
+  case 0xb9:
+    cpu_z80_cp(self, self->regs.byte.c);
+    break;
+  case 0xba:
+    cpu_z80_cp(self, self->regs.byte.d);
+    break;
+  case 0xbb:
+    cpu_z80_cp(self, self->regs.byte.e);
+    break;
+  case 0xbc:
+    cpu_z80_cp(self, self->regs.byte.iyh);
+    break;
+  case 0xbd:
+    cpu_z80_cp(self, self->regs.byte.iyl);
+    break;
+  case 0xbe:
+    cpu_z80_cp(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    break;
+  case 0xbf:
+    cpu_z80_cp(self, self->regs.byte.a);
+    break;
+  case 0xc0:
+    cpu_z80_ret(self, !self->regs.bit.zf);
+    break;
+  case 0xc1:
+    cpu_z80_pop(self, CPU_Z80_EA_BC);
+    break;
+  case 0xc2:
+    cpu_z80_jp(self, !self->regs.bit.zf, cpu_z80_fetch_word(self));
+    break;
+  case 0xc3:
+    cpu_z80_jp(self, true, cpu_z80_fetch_word(self));
+    break;
+  case 0xc4:
+    cpu_z80_call(self, !self->regs.bit.zf, cpu_z80_fetch_word(self));
+    break;
+  case 0xc5:
+    cpu_z80_push(self, self->regs.word.bc);
+    break;
+  case 0xc6:
+    cpu_z80_add_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    break;
+  case 0xc7:
+    cpu_z80_call(self, true, 0);
+    break;
+  case 0xc8:
+    cpu_z80_ret(self, self->regs.bit.zf);
+    break;
+  case 0xc9:
+    cpu_z80_ret(self, true);
+    break;
+  case 0xca:
+    cpu_z80_jp(self, self->regs.bit.zf, cpu_z80_fetch_word(self));
+    break;
+  case 0xcb:
+    cpu_z80_execute_fd_cb(self);
+    break;
+  case 0xcc:
+    cpu_z80_call(self, self->regs.bit.zf, cpu_z80_fetch_word(self));
+    break;
+  case 0xcd:
+    cpu_z80_call(self, true, cpu_z80_fetch_word(self));
+    break;
+  case 0xce:
+    cpu_z80_adc_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    break;
+  case 0xcf:
+    cpu_z80_call(self, true, 8);
+    break;
+  case 0xd0:
+    cpu_z80_ret(self, !self->regs.bit.cf);
+    break;
+  case 0xd1:
+    cpu_z80_pop(self, CPU_Z80_EA_DE);
+    break;
+  case 0xd2:
+    cpu_z80_jp(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
+    break;
+  case 0xd3:
+    cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs.byte.a);
+    break;
+  case 0xd4:
+    cpu_z80_call(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
+    break;
+  case 0xd5:
+    cpu_z80_push(self, self->regs.word.de);
+    break;
+  case 0xd6:
+    cpu_z80_sub(self, cpu_z80_fetch_byte(self));
+    break;
+  case 0xd7:
+    cpu_z80_call(self, true, 0x10);
+    break;
+  case 0xd8:
+    cpu_z80_ret(self, self->regs.bit.cf);
+    break;
+  case 0xd9:
+    cpu_z80_ex(self, CPU_Z80_EA_BC, CPU_Z80_EA_BC_PRIME);
+    cpu_z80_ex(self, CPU_Z80_EA_DE, CPU_Z80_EA_DE_PRIME);
+    cpu_z80_ex(self, CPU_Z80_EA_HL, CPU_Z80_EA_HL_PRIME);
+    break;
+  case 0xda:
+    cpu_z80_jp(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
+    break;
+  case 0xdb:
+    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)));
+    break;
+  case 0xdc:
+    cpu_z80_call(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
+    break;
+  case 0xdd:
     cpu_z80_ill(self);
     break;
-  case 0xff:
+  case 0xde:
+    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    break;
+  case 0xdf:
+    cpu_z80_call(self, true, 0x18);
+    break;
+  case 0xe0:
+    cpu_z80_ret(self, self->regs.bit.pvf);
+    break;
+  case 0xe1:
+    cpu_z80_pop(self, CPU_Z80_EA_IY);
+    break;
+  case 0xe2:
+    cpu_z80_jp(self, self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    break;
+  case 0xe3:
+    cpu_z80_ex(self, self->regs.word.sp, CPU_Z80_EA_IY);
+    break;
+  case 0xe4:
+    cpu_z80_call(self, self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    break;
+  case 0xe5:
+    cpu_z80_push(self, self->regs.word.iy);
+    break;
+  case 0xe6:
+    cpu_z80_and(self, cpu_z80_fetch_byte(self));
+    break;
+  case 0xe7:
+    cpu_z80_call(self, true, 0x20);
+    break;
+  case 0xe8:
+    cpu_z80_ret(self, !self->regs.bit.pvf);
+    break;
+  case 0xe9:
+    cpu_z80_jp(self, true, cpu_z80_read_word(self, self->regs.word.iy));
+    break;
+  case 0xea:
+    cpu_z80_jp(self, !self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    break;
+  case 0xeb:
+    cpu_z80_ex(self, CPU_Z80_EA_DE, CPU_Z80_EA_HL);
+    break;
+  case 0xec:
+    cpu_z80_call(self, !self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    break;
+  case 0xed:
+    cpu_z80_ill(self);
+    break;
+  case 0xee:
+    cpu_z80_xor(self, cpu_z80_fetch_byte(self));
+    break;
+  case 0xef:
+    cpu_z80_call(self, true, 0x28);
+    break;
+  case 0xf0:
+    cpu_z80_ret(self, !self->regs.bit.sf);
+    break;
+  case 0xf1:
+    cpu_z80_pop(self, CPU_Z80_EA_AF);
+    break;
+  case 0xf2:
+    cpu_z80_jp(self, !self->regs.bit.sf, cpu_z80_fetch_word(self));
+    break;
+  case 0xf3:
+    cpu_z80_di(self);
+    break;
+  case 0xf4:
+    cpu_z80_call(self, !self->regs.bit.sf, cpu_z80_fetch_word(self));
+    break;
+  case 0xf5:
+    cpu_z80_push(self, self->regs.word.af);
+    break;
+  case 0xf6:
+    cpu_z80_or(self, cpu_z80_fetch_byte(self));
+    break;
+  case 0xf7:
+    cpu_z80_call(self, true, 0x30);
+    break;
+  case 0xf8:
+    cpu_z80_ret(self, self->regs.bit.sf);
+    break;
+  case 0xf9:
+    cpu_z80_ld_word(self, CPU_Z80_EA_SP, self->regs.word.iy);
+    break;
+  case 0xfa:
+    cpu_z80_jp(self, self->regs.bit.sf, cpu_z80_fetch_word(self));
+    break;
+  case 0xfb:
+    cpu_z80_ei(self);
+    break;
+  case 0xfc:
+    cpu_z80_call(self, self->regs.bit.sf, cpu_z80_fetch_word(self));
+    break;
+  case 0xfd:
     cpu_z80_ill(self);
     break;
+  case 0xfe:
+    cpu_z80_cp(self, cpu_z80_fetch_byte(self));
+    break;
+  case 0xff:
+    cpu_z80_call(self, true, 0x38);
+    break;
   }
 }
 
-void cpu_z80_execute_fd(struct cpu_z80 *self) {
+void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
+  int ea = cpu_z80_displacement(self, self->regs.word.iy);
   switch (cpu_z80_fetch_byte(self)) {
   case 0x00:
-    cpu_z80_nop(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_B);
     break;
   case 0x01:
-    cpu_z80_ld_word(self, CPU_Z80_EA_BC, cpu_z80_fetch_word(self));
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_C);
     break;
   case 0x02:
-    cpu_z80_ld_byte(self, self->regs.word.bc, self->regs.byte.a);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_D);
     break;
   case 0x03:
-    cpu_z80_inc_word(self, CPU_Z80_EA_BC);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_E);
     break;
   case 0x04:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_B);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_H);
     break;
   case 0x05:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_B);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x06:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, cpu_z80_fetch_byte(self));
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x07:
-    cpu_z80_rlca(self);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_A);
     break;
   case 0x08:
-    cpu_z80_ex(self, CPU_Z80_EA_AF, CPU_Z80_EA_AF_PRIME);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_B);
     break;
   case 0x09:
-    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.bc);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_C);
     break;
   case 0x0a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, self->regs.word.bc));
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_D);
     break;
   case 0x0b:
-    cpu_z80_dec_word(self, CPU_Z80_EA_BC);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_E);
     break;
   case 0x0c:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_C);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_H);
     break;
   case 0x0d:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_C);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x0e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, cpu_z80_fetch_byte(self));
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x0f:
-    cpu_z80_rrca(self);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_A);
     break;
   case 0x10:
-    cpu_z80_djnz(self, cpu_z80_relative(self));
+    cpu_z80_rl(self, ea, CPU_Z80_EA_B);
     break;
   case 0x11:
-    cpu_z80_ld_word(self, CPU_Z80_EA_DE, cpu_z80_fetch_word(self));
+    cpu_z80_rl(self, ea, CPU_Z80_EA_C);
     break;
   case 0x12:
-    cpu_z80_ld_byte(self, self->regs.word.de, self->regs.byte.a);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_D);
     break;
   case 0x13:
-    cpu_z80_inc_word(self, CPU_Z80_EA_DE);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_E);
     break;
   case 0x14:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_D);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_H);
     break;
   case 0x15:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_D);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x16:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, cpu_z80_fetch_byte(self));
+    cpu_z80_rl(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x17:
-    cpu_z80_rla(self);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_A);
     break;
   case 0x18:
-    cpu_z80_jr(self, true, cpu_z80_relative(self));
+    cpu_z80_rr(self, ea, CPU_Z80_EA_B);
     break;
   case 0x19:
-    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.de);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_C);
     break;
   case 0x1a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, self->regs.word.de));
+    cpu_z80_rr(self, ea, CPU_Z80_EA_D);
     break;
   case 0x1b:
-    cpu_z80_dec_word(self, CPU_Z80_EA_DE);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_E);
     break;
   case 0x1c:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_E);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_H);
     break;
   case 0x1d:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_E);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_L);
     break;
   case 0x1e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, cpu_z80_fetch_byte(self));
+    cpu_z80_rr(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x1f:
-    cpu_z80_rra(self);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_A);
     break;
   case 0x20:
-    cpu_z80_jr(self, !self->regs.bit.zf, cpu_z80_relative(self));
+    cpu_z80_sla(self, ea, CPU_Z80_EA_B);
     break;
   case 0x21:
-    cpu_z80_ld_word(self, CPU_Z80_EA_IY, cpu_z80_fetch_word(self));
+    cpu_z80_sla(self, ea, CPU_Z80_EA_C);
     break;
   case 0x22:
-    cpu_z80_ld_word(self, cpu_z80_fetch_word(self), self->regs.word.iy);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_D);
     break;
   case 0x23:
-    cpu_z80_inc_word(self, CPU_Z80_EA_IY);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_E);
     break;
   case 0x24:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_IYH);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_H);
     break;
   case 0x25:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_IYH);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_L);
     break;
   case 0x26:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, cpu_z80_fetch_byte(self));
+    cpu_z80_sla(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x27:
-    cpu_z80_daa(self);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_A);
     break;
   case 0x28:
-    cpu_z80_jr(self, self->regs.bit.zf, cpu_z80_relative(self));
+    cpu_z80_sra(self, ea, CPU_Z80_EA_B);
     break;
   case 0x29:
-    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.iy);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_C);
     break;
   case 0x2a:
-    cpu_z80_ld_word(self, CPU_Z80_EA_IY, cpu_z80_read_word(self, cpu_z80_fetch_word(self)));
+    cpu_z80_sra(self, ea, CPU_Z80_EA_D);
     break;
   case 0x2b:
-    cpu_z80_dec_word(self, CPU_Z80_EA_IY);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_E);
     break;
   case 0x2c:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_IYL);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_H);
     break;
   case 0x2d:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_IYL);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_L);
     break;
   case 0x2e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, cpu_z80_fetch_byte(self));
+    cpu_z80_sra(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x2f:
-    cpu_z80_cpl(self);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_A);
     break;
   case 0x30:
-    cpu_z80_jr(self, !self->regs.bit.cf, cpu_z80_relative(self));
+    cpu_z80_sll(self, ea, CPU_Z80_EA_B);
     break;
   case 0x31:
-    cpu_z80_ld_word(self, CPU_Z80_EA_SP, cpu_z80_fetch_word(self));
+    cpu_z80_sll(self, ea, CPU_Z80_EA_C);
     break;
   case 0x32:
-    cpu_z80_ld_byte(self, cpu_z80_fetch_word(self), self->regs.byte.a);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_D);
     break;
   case 0x33:
-    cpu_z80_inc_word(self, CPU_Z80_EA_SP);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_E);
     break;
   case 0x34:
-    cpu_z80_inc_byte(self, cpu_z80_displacement(self, self->regs.word.iy));
+    cpu_z80_sll(self, ea, CPU_Z80_EA_H);
     break;
   case 0x35:
-    cpu_z80_dec_byte(self, cpu_z80_displacement(self, self->regs.word.iy));
+    cpu_z80_sll(self, ea, CPU_Z80_EA_L);
     break;
   case 0x36:
-    {
-      int ea = cpu_z80_displacement(self, self->regs.word.iy);
-      cpu_z80_ld_byte(self, ea, cpu_z80_fetch_byte(self));
-    }
+    cpu_z80_sll(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x37:
-    cpu_z80_scf(self);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_A);
     break;
   case 0x38:
-    cpu_z80_jr(self, self->regs.bit.cf, cpu_z80_relative(self));
+    cpu_z80_srl(self, ea, CPU_Z80_EA_B);
     break;
   case 0x39:
-    cpu_z80_add_word(self, CPU_Z80_EA_IY, self->regs.word.sp);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_C);
     break;
   case 0x3a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_fetch_word(self)));
+    cpu_z80_srl(self, ea, CPU_Z80_EA_D);
     break;
   case 0x3b:
-    cpu_z80_dec_word(self, CPU_Z80_EA_SP);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_E);
     break;
   case 0x3c:
-    cpu_z80_inc_byte(self, CPU_Z80_EA_A);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_H);
     break;
   case 0x3d:
-    cpu_z80_dec_byte(self, CPU_Z80_EA_A);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x3e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    cpu_z80_srl(self, ea, CPU_Z80_EA_NONE);
     break;
   case 0x3f:
-    cpu_z80_ccf(self);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_A);
     break;
   case 0x40:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.b);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x41:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.c);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x42:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.d);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x43:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.e);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x44:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.iyh);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x45:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.iyl);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x46:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x47:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_B, self->regs.byte.a);
+    cpu_z80_bit(self, 0, cpu_z80_read_byte(self, ea));
     break;
   case 0x48:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.b);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x49:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.c);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.d);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4b:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.e);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4c:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.iyh);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4d:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.iyl);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x4f:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_C, self->regs.byte.a);
+    cpu_z80_bit(self, 1, cpu_z80_read_byte(self, ea));
     break;
   case 0x50:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.b);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x51:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.c);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x52:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.d);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x53:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.e);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x54:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.iyh);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x55:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.iyl);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x56:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x57:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_D, self->regs.byte.a);
+    cpu_z80_bit(self, 2, cpu_z80_read_byte(self, ea));
     break;
   case 0x58:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.b);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x59:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.c);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.d);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5b:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.e);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5c:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.iyh);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5d:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.iyl);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x5f:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_E, self->regs.byte.a);
+    cpu_z80_bit(self, 3, cpu_z80_read_byte(self, ea));
     break;
   case 0x60:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.b);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x61:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.c);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x62:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.d);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x63:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.e);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x64:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.iyh);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x65:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.iyl);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x66:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_H, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x67:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYH, self->regs.byte.a);
+    cpu_z80_bit(self, 4, cpu_z80_read_byte(self, ea));
     break;
   case 0x68:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.b);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x69:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.c);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.d);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6b:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.e);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6c:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.iyh);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6d:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.iyl);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_L, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x6f:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_IYL, self->regs.byte.a);
+    cpu_z80_bit(self, 5, cpu_z80_read_byte(self, ea));
     break;
   case 0x70:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.b);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x71:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.c);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x72:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.d);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x73:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.e);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x74:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.h);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x75:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.l);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x76:
-    cpu_z80_halt(self);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x77:
-    cpu_z80_ld_byte(self, cpu_z80_displacement(self, self->regs.word.iy), self->regs.byte.a);
+    cpu_z80_bit(self, 6, cpu_z80_read_byte(self, ea));
     break;
   case 0x78:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x79:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7a:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7b:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7c:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7d:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7e:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x7f:
-    cpu_z80_ld_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    cpu_z80_bit(self, 7, cpu_z80_read_byte(self, ea));
     break;
   case 0x80:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_B);
     break;
   case 0x81:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_C);
     break;
   case 0x82:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_D);
     break;
   case 0x83:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_E);
     break;
   case 0x84:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_H);
     break;
   case 0x85:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0x86:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_NONE);
     break;
   case 0x87:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_A);
     break;
   case 0x88:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_B);
     break;
   case 0x89:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_C);
     break;
   case 0x8a:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_D);
     break;
   case 0x8b:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_E);
     break;
   case 0x8c:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_H);
     break;
   case 0x8d:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0x8e:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_NONE);
     break;
   case 0x8f:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_A);
     break;
   case 0x90:
-    cpu_z80_sub(self, self->regs.byte.b);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_B);
     break;
   case 0x91:
-    cpu_z80_sub(self, self->regs.byte.c);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_C);
     break;
   case 0x92:
-    cpu_z80_sub(self, self->regs.byte.d);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_D);
     break;
   case 0x93:
-    cpu_z80_sub(self, self->regs.byte.e);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_E);
     break;
   case 0x94:
-    cpu_z80_sub(self, self->regs.byte.iyh);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_H);
     break;
   case 0x95:
-    cpu_z80_sub(self, self->regs.byte.iyl);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0x96:
-    cpu_z80_sub(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_NONE);
     break;
   case 0x97:
-    cpu_z80_sub(self, self->regs.byte.a);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_A);
     break;
   case 0x98:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.b);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_B);
     break;
   case 0x99:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.c);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_C);
     break;
   case 0x9a:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.d);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_D);
     break;
   case 0x9b:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.e);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_E);
     break;
   case 0x9c:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyh);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_H);
     break;
   case 0x9d:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.iyl);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0x9e:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_NONE);
     break;
   case 0x9f:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, self->regs.byte.a);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_A);
     break;
   case 0xa0:
-    cpu_z80_and(self, self->regs.byte.b);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_B);
     break;
   case 0xa1:
-    cpu_z80_and(self, self->regs.byte.c);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_C);
     break;
   case 0xa2:
-    cpu_z80_and(self, self->regs.byte.d);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_D);
     break;
   case 0xa3:
-    cpu_z80_and(self, self->regs.byte.e);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_E);
     break;
   case 0xa4:
-    cpu_z80_and(self, self->regs.byte.iyh);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_H);
     break;
   case 0xa5:
-    cpu_z80_and(self, self->regs.byte.iyl);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xa6:
-    cpu_z80_and(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_NONE);
     break;
   case 0xa7:
-    cpu_z80_and(self, self->regs.byte.a);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_A);
     break;
   case 0xa8:
-    cpu_z80_xor(self, self->regs.byte.b);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_B);
     break;
   case 0xa9:
-    cpu_z80_xor(self, self->regs.byte.c);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_C);
     break;
   case 0xaa:
-    cpu_z80_xor(self, self->regs.byte.d);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_D);
     break;
   case 0xab:
-    cpu_z80_xor(self, self->regs.byte.e);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_E);
     break;
   case 0xac:
-    cpu_z80_xor(self, self->regs.byte.iyh);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_H);
     break;
   case 0xad:
-    cpu_z80_xor(self, self->regs.byte.iyl);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xae:
-    cpu_z80_xor(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_NONE);
     break;
   case 0xaf:
-    cpu_z80_xor(self, self->regs.byte.a);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_A);
     break;
   case 0xb0:
-    cpu_z80_or(self, self->regs.byte.b);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_B);
     break;
   case 0xb1:
-    cpu_z80_or(self, self->regs.byte.c);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_C);
     break;
   case 0xb2:
-    cpu_z80_or(self, self->regs.byte.d);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_D);
     break;
   case 0xb3:
-    cpu_z80_or(self, self->regs.byte.e);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_E);
     break;
   case 0xb4:
-    cpu_z80_or(self, self->regs.byte.iyh);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_H);
     break;
   case 0xb5:
-    cpu_z80_or(self, self->regs.byte.iyl);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xb6:
-    cpu_z80_or(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_NONE);
     break;
   case 0xb7:
-    cpu_z80_or(self, self->regs.byte.a);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_A);
     break;
   case 0xb8:
-    cpu_z80_cp(self, self->regs.byte.b);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_B);
     break;
   case 0xb9:
-    cpu_z80_cp(self, self->regs.byte.c);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_C);
     break;
   case 0xba:
-    cpu_z80_cp(self, self->regs.byte.d);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_D);
     break;
   case 0xbb:
-    cpu_z80_cp(self, self->regs.byte.e);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_E);
     break;
   case 0xbc:
-    cpu_z80_cp(self, self->regs.byte.iyh);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_H);
     break;
   case 0xbd:
-    cpu_z80_cp(self, self->regs.byte.iyl);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xbe:
-    cpu_z80_cp(self, cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy)));
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_NONE);
     break;
   case 0xbf:
-    cpu_z80_cp(self, self->regs.byte.a);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_A);
     break;
   case 0xc0:
-    cpu_z80_ret(self, !self->regs.bit.zf);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_B);
     break;
   case 0xc1:
-    cpu_z80_pop(self, CPU_Z80_EA_BC);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_C);
     break;
   case 0xc2:
-    cpu_z80_jp(self, !self->regs.bit.zf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_D);
     break;
   case 0xc3:
-    cpu_z80_jp(self, true, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_E);
     break;
   case 0xc4:
-    cpu_z80_call(self, !self->regs.bit.zf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_H);
     break;
   case 0xc5:
-    cpu_z80_push(self, self->regs.word.bc);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0xc6:
-    cpu_z80_add_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_NONE);
     break;
   case 0xc7:
-    cpu_z80_call(self, true, 0);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_A);
     break;
   case 0xc8:
-    cpu_z80_ret(self, self->regs.bit.zf);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_B);
     break;
   case 0xc9:
-    cpu_z80_ret(self, true);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_C);
     break;
   case 0xca:
-    cpu_z80_jp(self, self->regs.bit.zf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_D);
     break;
   case 0xcb:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_E);
     break;
   case 0xcc:
-    cpu_z80_call(self, self->regs.bit.zf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_H);
     break;
   case 0xcd:
-    cpu_z80_call(self, true, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0xce:
-    cpu_z80_adc_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_NONE);
     break;
   case 0xcf:
-    cpu_z80_call(self, true, 8);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_A);
     break;
   case 0xd0:
-    cpu_z80_ret(self, !self->regs.bit.cf);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_B);
     break;
   case 0xd1:
-    cpu_z80_pop(self, CPU_Z80_EA_DE);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_C);
     break;
   case 0xd2:
-    cpu_z80_jp(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_D);
     break;
   case 0xd3:
-    cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs.byte.a);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_E);
     break;
   case 0xd4:
-    cpu_z80_call(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_H);
     break;
   case 0xd5:
-    cpu_z80_push(self, self->regs.word.de);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0xd6:
-    cpu_z80_sub(self, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_NONE);
     break;
   case 0xd7:
-    cpu_z80_call(self, true, 0x10);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_A);
     break;
   case 0xd8:
-    cpu_z80_ret(self, self->regs.bit.cf);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_B);
     break;
   case 0xd9:
-    cpu_z80_ex(self, CPU_Z80_EA_BC, CPU_Z80_EA_BC_PRIME);
-    cpu_z80_ex(self, CPU_Z80_EA_DE, CPU_Z80_EA_DE_PRIME);
-    cpu_z80_ex(self, CPU_Z80_EA_HL, CPU_Z80_EA_HL_PRIME);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_C);
     break;
   case 0xda:
-    cpu_z80_jp(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_D);
     break;
   case 0xdb:
-    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)));
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_E);
     break;
   case 0xdc:
-    cpu_z80_call(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_H);
     break;
   case 0xdd:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0xde:
-    cpu_z80_sbc_byte(self, CPU_Z80_EA_A, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_NONE);
     break;
   case 0xdf:
-    cpu_z80_call(self, true, 0x18);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_A);
     break;
   case 0xe0:
-    cpu_z80_ret(self, self->regs.bit.pvf);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_B);
     break;
   case 0xe1:
-    cpu_z80_pop(self, CPU_Z80_EA_IY);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_C);
     break;
   case 0xe2:
-    cpu_z80_jp(self, self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_D);
     break;
   case 0xe3:
-    cpu_z80_ex(self, self->regs.word.sp, CPU_Z80_EA_IY);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_E);
     break;
   case 0xe4:
-    cpu_z80_call(self, self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_H);
     break;
   case 0xe5:
-    cpu_z80_push(self, self->regs.word.iy);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xe6:
-    cpu_z80_and(self, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_NONE);
     break;
   case 0xe7:
-    cpu_z80_call(self, true, 0x20);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_A);
     break;
   case 0xe8:
-    cpu_z80_ret(self, !self->regs.bit.pvf);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_B);
     break;
   case 0xe9:
-    cpu_z80_jp(self, true, cpu_z80_read_word(self, self->regs.word.iy));
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_C);
     break;
   case 0xea:
-    cpu_z80_jp(self, !self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_D);
     break;
   case 0xeb:
-    cpu_z80_ex(self, CPU_Z80_EA_DE, CPU_Z80_EA_HL);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_E);
     break;
   case 0xec:
-    cpu_z80_call(self, !self->regs.bit.pvf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_H);
     break;
   case 0xed:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xee:
-    cpu_z80_xor(self, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_NONE);
     break;
   case 0xef:
-    cpu_z80_call(self, true, 0x28);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_A);
     break;
   case 0xf0:
-    cpu_z80_ret(self, !self->regs.bit.sf);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_B);
     break;
   case 0xf1:
-    cpu_z80_pop(self, CPU_Z80_EA_AF);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_C);
     break;
   case 0xf2:
-    cpu_z80_jp(self, !self->regs.bit.sf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_D);
     break;
   case 0xf3:
-    cpu_z80_di(self);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_E);
     break;
   case 0xf4:
-    cpu_z80_call(self, !self->regs.bit.sf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_H);
     break;
   case 0xf5:
-    cpu_z80_push(self, self->regs.word.af);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xf6:
-    cpu_z80_or(self, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_NONE);
     break;
   case 0xf7:
-    cpu_z80_call(self, true, 0x30);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_A);
     break;
   case 0xf8:
-    cpu_z80_ret(self, self->regs.bit.sf);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_B);
     break;
   case 0xf9:
-    cpu_z80_ld_word(self, CPU_Z80_EA_SP, self->regs.word.iy);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_C);
     break;
   case 0xfa:
-    cpu_z80_jp(self, self->regs.bit.sf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_D);
     break;
   case 0xfb:
-    cpu_z80_ei(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_E);
     break;
   case 0xfc:
-    cpu_z80_call(self, self->regs.bit.sf, cpu_z80_fetch_word(self));
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_H);
     break;
   case 0xfd:
-    cpu_z80_ill(self);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xfe:
-    cpu_z80_cp(self, cpu_z80_fetch_byte(self));
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_NONE);
     break;
   case 0xff:
-    cpu_z80_call(self, true, 0x38);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_A);
     break;
   }
 }
+
index 27527a0..c465c5e 100644 (file)
--- a/cpu_z80.h
+++ b/cpu_z80.h
@@ -473,7 +473,7 @@ static ALWAYS_INLINE void cpu_z80_push(struct cpu_z80 *self, int rvalue) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_res(struct cpu_z80 *self, int n, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_res(struct cpu_z80 *self, int n, int lvalue0, int lvalue1) {
   abort();
 }
 
@@ -489,7 +489,7 @@ static ALWAYS_INLINE void cpu_z80_retn(struct cpu_z80 *self) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_rl(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_rl(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
@@ -497,7 +497,7 @@ static ALWAYS_INLINE void cpu_z80_rla(struct cpu_z80 *self) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_rlc(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_rlc(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
@@ -509,7 +509,7 @@ static ALWAYS_INLINE void cpu_z80_rld(struct cpu_z80 *self) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_rr(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_rr(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
@@ -517,7 +517,7 @@ static ALWAYS_INLINE void cpu_z80_rra(struct cpu_z80 *self) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_rrc(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_rrc(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
@@ -541,23 +541,23 @@ static ALWAYS_INLINE void cpu_z80_scf(struct cpu_z80 *self) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_set(struct cpu_z80 *self, int n, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_set(struct cpu_z80 *self, int n, int lvalue0, int lvalue1) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_sla(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_sla(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_sll(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_sll(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_sra(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_sra(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_z80_srl(struct cpu_z80 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_z80_srl(struct cpu_z80 *self, int lvalue0, int lvalue1) {
   abort();
 }
 
@@ -580,7 +580,9 @@ void cpu_z80_init(
 void cpu_z80_execute(struct cpu_z80 *self);
 void cpu_z80_execute_cb(struct cpu_z80 *self);
 void cpu_z80_execute_dd(struct cpu_z80 *self);
+void cpu_z80_execute_dd_cb(struct cpu_z80 *self);
 void cpu_z80_execute_ed(struct cpu_z80 *self);
 void cpu_z80_execute_fd(struct cpu_z80 *self);
+void cpu_z80_execute_fd_cb(struct cpu_z80 *self);
 
 #endif
index 58d11ec..bdc6157 100755 (executable)
@@ -53,7 +53,7 @@ lvalue_modes = {
 }
 
 print('void cpu_65c02_execute(struct cpu_65c02 *self) {')
-print('  switch (cpu_z80_fetch_byte(self)) {')
+print('  switch (cpu_65c02_fetch_byte(self)) {')
 for i in range(0x100):
   print(f'  case 0x{i:02x}:')
   if i == 0x64: # cope with py65 disassembler bug
index 094ace2..9a6e717 100644 (file)
@@ -1,26 +1,26 @@
-s/cpu_65c02_ill(self/cpu_65c02_ill11(self/g
-s/cpu_65c02_rmb\([0-7]\)(self/cpu_65c02_rmb(self, \1/g
-s/cpu_65c02_smb\([0-7]\)(self/cpu_65c02_smb(self, \1/g
-s/cpu_65c02_ph\([axyp]\)(self/cpu_65c02_ph(self, self->regs.byte.\1/g
-s/cpu_65c02_pl\([axy]\)(self/cpu_65c02_pl(self, CPU_65C02_EA_\1/g
-s/cpu_65c02_bpl(self/cpu_65c02_bnc(self/g
-s/cpu_65c02_bmi(self/cpu_65c02_bns(self/g
-s/cpu_65c02_bne(self/cpu_65c02_bzc(self/g
-s/cpu_65c02_beq(self/cpu_65c02_bzs(self/g
-s/cpu_65c02_bra(self/cpu_65c02_bra(self, true/g
-s/cpu_65c02_b\([czvn]\)c(self/cpu_65c02_bra(self, !self->regs.bit.\1f/g
-s/cpu_65c02_b\([czvn]\)s(self/cpu_65c02_bra(self, self->regs.bit.\1f/g
-s/cpu_65c02_stz(self/cpu_65c02_st(self, 0/g
-s/cpu_65c02_st\([axy]\)(self/cpu_65c02_st(self, self->regs.byte.\1/g
-s/cpu_65c02_ld\([axy]\)(self/cpu_65c02_ld(self, CPU_65C02_EA_\1/g
-s/cpu_65c02_txs(self/cpu_65c02_st(self, self->regs.byte.x, CPU_65C02_EA_S)/g
-s/cpu_65c02_t\([axys]\)\([axys]\)(self/cpu_65c02_ld(self, CPU_65C02_EA_\2, self->regs.byte.\1/g
-s/cpu_65c02_cl\([cidv]\)(self/cpu_65c02_cl(self, CPU_65C02_REG_P_BIT_\1/g
-s/cpu_65c02_se\([cidv]\)(self/cpu_65c02_se(self, CPU_65C02_REG_P_BIT_\1/g
-s/cpu_65c02_in\([xy]\)(self/cpu_65c02_inc(self, CPU_65C02_EA_\1/g
-s/cpu_65c02_de\([xy]\)(self/cpu_65c02_dec(self, CPU_65C02_EA_\1/g
-s/cpu_65c02_cmp(self/cpu_65c02_cmp(self, self->regs.byte.a/g
-s/cpu_65c02_cp\([xy]\)(self/cpu_65c02_cmp(self, self->regs.byte.\1/g
+s/cpu_65c02_ill(self/cpu_65c02_ill11(self/
+s/cpu_65c02_rmb\([0-7]\)(self/cpu_65c02_rmb(self, \1/
+s/cpu_65c02_smb\([0-7]\)(self/cpu_65c02_smb(self, \1/
+s/cpu_65c02_ph\([axyp]\)(self/cpu_65c02_ph(self, self->regs.byte.\1/
+s/cpu_65c02_pl\([axy]\)(self/cpu_65c02_pl(self, CPU_65C02_EA_\1/
+s/cpu_65c02_bpl(self/cpu_65c02_bnc(self/
+s/cpu_65c02_bmi(self/cpu_65c02_bns(self/
+s/cpu_65c02_bne(self/cpu_65c02_bzc(self/
+s/cpu_65c02_beq(self/cpu_65c02_bzs(self/
+s/cpu_65c02_bra(self/cpu_65c02_bra(self, true/
+s/cpu_65c02_b\([czvn]\)c(self/cpu_65c02_bra(self, !self->regs.bit.\1f/
+s/cpu_65c02_b\([czvn]\)s(self/cpu_65c02_bra(self, self->regs.bit.\1f/
+s/cpu_65c02_stz(self/cpu_65c02_st(self, 0/
+s/cpu_65c02_st\([axy]\)(self/cpu_65c02_st(self, self->regs.byte.\1/
+s/cpu_65c02_ld\([axy]\)(self/cpu_65c02_ld(self, CPU_65C02_EA_\1/
+s/cpu_65c02_txs(self/cpu_65c02_st(self, self->regs.byte.x, CPU_65C02_EA_S)/
+s/cpu_65c02_t\([axys]\)\([axys]\)(self/cpu_65c02_ld(self, CPU_65C02_EA_\2, self->regs.byte.\1/
+s/cpu_65c02_cl\([cidv]\)(self/cpu_65c02_cl(self, CPU_65C02_REG_P_BIT_\1/
+s/cpu_65c02_se\([cidv]\)(self/cpu_65c02_se(self, CPU_65C02_REG_P_BIT_\1/
+s/cpu_65c02_in\([xy]\)(self/cpu_65c02_inc(self, CPU_65C02_EA_\1/
+s/cpu_65c02_de\([xy]\)(self/cpu_65c02_dec(self, CPU_65C02_EA_\1/
+s/cpu_65c02_cmp(self/cpu_65c02_cmp(self, self->regs.byte.a/
+s/cpu_65c02_cp\([xy]\)(self/cpu_65c02_cmp(self, self->regs.byte.\1/
 s/CPU_65C02_EA_a/CPU_65C02_EA_A/g
 s/CPU_65C02_EA_x/CPU_65C02_EA_X/g
 s/CPU_65C02_EA_y/CPU_65C02_EA_Y/g
index 986e28f..d5292c4 100755 (executable)
@@ -87,8 +87,6 @@ byte_rvalue_modes = {
   '(bc)': 'cpu_z80_read_byte(self, self->regs.word.bc)',
   '(de)': 'cpu_z80_read_byte(self, self->regs.word.de)',
   '(hl)': 'cpu_z80_read_byte(self, self->regs.word.hl)',
-  #'(ix)': 'cpu_z80_read_byte(self->regs.word.ix)',
-  #'(iy)': 'cpu_z80_read_byte(self->regs.word.iy)',
   '(ix+0x12)': 'cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.ix))',
   '(iy+0x12)': 'cpu_z80_read_byte(self, cpu_z80_displacement(self, self->regs.word.iy))',
   '(0x0012)': 'cpu_z80_in_byte(self, cpu_z80_fetch_byte(self))',
@@ -121,8 +119,6 @@ byte_lvalue_modes = {
   '(bc)': 'self->regs.word.bc',
   '(de)': 'self->regs.word.de',
   '(hl)': 'self->regs.word.hl',
-  #'(ix)': 'self->regs.word.ix',
-  #'(iy)': 'self->regs.word.iy',
   '(ix+0x12)': 'cpu_z80_displacement(self, self->regs.word.ix)',
   '(iy+0x12)': 'cpu_z80_displacement(self, self->regs.word.iy)',
   '(0x0012)': 'cpu_z80_fetch_byte(self)',
@@ -196,27 +192,58 @@ word_lvalue_modes = {
   'pe': '!self->regs.bit.pvf',
 }
 
-prefixes = [[], [0xcb], [0xdd], [0xed], [0xfd]]
-prefix_strings = ['', '_cb', '_dd', '_ed', '_fd']
-for i in range(0x500):
+# opcodes allowing predication need a "true" parameter when not predicated
+pred_opcodes = {
+  'jr': 3,
+  'jp': 3,
+  'call': 3,
+  'ret': 2,
+}
+
+# CB-prefixed opcodes other than "bit" need an extra lvalue parameter to
+# store a copy of the result in, for undocumented DDCB/FDCB instructions
+cb_opcodes = {
+  'rlc': 3,
+  'rrc': 3,
+  'rl': 3,
+  'rr': 3,
+  'sla': 3,
+  'sra': 3,
+  'sll': 3,
+  'srl': 3,
+  'res': 4,
+  'set': 4,
+}
+
+prefixes = [[], [0xcb], [0xdd], [0xdd, 0xcb], [0xed], [0xfd], [0xfd, 0xcb]]
+for i in range(0x700):
   if (i & 0xff) == 0:
     print(
-      f'void cpu_z80_execute{prefix_strings[i >> 8]:s}(struct cpu_z80 *self) {{'
+      'void cpu_z80_execute{0:s}(struct cpu_z80 *self) {{'.format(
+        ''.join([f'_{j:02x}' for j in prefixes[i >> 8]])
+      )
     )
     print('  switch (cpu_z80_fetch_byte(self)) {')
   print(f'  case 0x{i & 0xff:02x}:')
-  if [i] in prefixes:
-    print(f'    cpu_z80_execute_{i:02x}(self);')
+  opcodes = prefixes[i >> 8] + [i & 0xff]
+  if opcodes in prefixes:
+    print(
+      '    cpu_z80_execute{0:s}(self);'.format(
+        ''.join([f'_{j:02x}' for j in opcodes])
+      )
+    )
   else:
     instr = z80dis.z80.disasm(
-      bytes(prefixes[i >> 8] + [i & 0xff, 0x12, 0x34, 0x56, 0x78])
+      # for DDCB and FDCB the displacement goes before the next opcode
+      bytes(opcodes[:2] + [0x12] + opcodes[2:] + [0x34])
     ).lower().split()
     if len(instr) == 0:
       instr = ['ill']
     elif len(instr) >= 2:
-      instr[1:] = instr[1].split(',')
-      if instr == ['ld', 'h', 'sll']:
-        instr = ['ill'] # deal with this later
+      instr[1:] = [k for j in instr[1:] for k in j.split(',')]
+    if len(instr) >= 4: # the undocumented DDCB and FDCB variants
+      assert instr[0] == 'ld'
+      instr = instr[2:] + instr[1:2] # "ld a,op (ix+n)" to "op (ix+n),a"
     #print('xxx', instr)
     suffix = ''
     if instr[0] not in byte_opcodes and instr[0] not in word_opcodes:
@@ -238,6 +265,10 @@ for i in range(0x500):
         instr[k] = word_lvalue_modes[instr[k]]
       for k in range(j, len(instr)):
         instr[k] = word_rvalue_modes[instr[k]]
+    if len(instr) < pred_opcodes.get(instr[0], 0):
+      instr[1:1] = ['true']
+    if len(instr) < cb_opcodes.get(instr[0], 0):
+      instr.append('CPU_Z80_EA_NONE')
     print(
       '    cpu_z80_{0:s}{1:s}(self{2:s});'.format(
         instr[0],
index a96670f..295e01c 100644 (file)
@@ -1,9 +1,9 @@
-s/cpu_z80_jr(self/cpu_z80_jr(self, true/g
-s/cpu_z80_jp(self/cpu_z80_jp(self, true/g
-s/cpu_z80_call(self/cpu_z80_call(self, true/g
-s/cpu_z80_ret(self/cpu_z80_ret(self, true/g
-s/cpu_z80_rst(self/cpu_z80_call(self, true/g
-s/(self, true, \(!\?self->regs\.bit\.\)/(self, \1/g
-s/cpu_z80_in(self, CPU_Z80_EA_F/cpu_z80_in(self, CPU_Z80_EA_NONE/g
+s/cpu_z80_rst(self/cpu_z80_call(self, true/
+s/(self, true, \(!\?self->regs\.bit\.\)/(self, \1/
+s/cpu_z80_in(self, CPU_Z80_EA_F/cpu_z80_in(self, CPU_Z80_EA_NONE/
 s/^    \(cpu_z80_ld_byte(self, \)\(cpu_z80_displacement(self, self->regs\.word\.i[xy])\)\(, cpu_z80_fetch_byte(self));\)$/    {\n      int ea = \2;\n      \1ea\3\n    }/
 s/^    cpu_z80_exx(self);$/    cpu_z80_ex(self, CPU_Z80_EA_BC, CPU_Z80_EA_BC_PRIME);\n    cpu_z80_ex(self, CPU_Z80_EA_DE, CPU_Z80_EA_DE_PRIME);\n    cpu_z80_ex(self, CPU_Z80_EA_HL, CPU_Z80_EA_HL_PRIME);/
+/^void cpu_z80_execute_dd_cb(struct cpu_z80 \*self) {$/,/^}$/s/cpu_z80_displacement(self, self->regs\.word\.ix)/ea/
+s/^void cpu_z80_execute_dd_cb(struct cpu_z80 \*self) {$/&\n  int ea = cpu_z80_displacement(self, self->regs.word.ix);/
+/^void cpu_z80_execute_fd_cb(struct cpu_z80 \*self) {$/,/^}$/s/cpu_z80_displacement(self, self->regs\.word\.iy)/ea/
+s/^void cpu_z80_execute_fd_cb(struct cpu_z80 \*self) {$/&\n  int ea = cpu_z80_displacement(self, self->regs.word.iy);/