Implement Z80 interrupt system, and 65C02/Z80 reset function
authorNick Downing <nick@ndcode.org>
Sat, 23 Jul 2022 04:18:44 +0000 (14:18 +1000)
committerNick Downing <nick@ndcode.org>
Sat, 23 Jul 2022 04:18:44 +0000 (14:18 +1000)
cpu_65c02.c
cpu_65c02.h
cpu_z80.c
cpu_z80.h
decode_z80.py
decode_z80.sed
emu_65c02.c
emu_z80.c

index a6520b1..ae741ee 100644 (file)
@@ -19,6 +19,13 @@ void cpu_65c02_init(
   self->write_byte_context = write_byte_context;
 }
 
+void cpu_65c02_reset(struct cpu_65c02 *self) {
+  self->regs.word.pc = cpu_65c02_read_word(self, CPU_65C02_RESET_VECTOR);
+  self->regs.byte.iflags = 0;
+  self->regs.bit._if = true;
+  self->regs.bit.df = false;
+}
+
 // instruction decode
 void cpu_65c02_execute(struct cpu_65c02 *self) {
   if (self->regs.bit.stp_flag) {
index 0fe8f24..e8d4e05 100644 (file)
 #define CPU_65C02_REG_P_BIT_N 7
 
 // special memory locations (negative address)
-#define CPU_65C02_EA_A (-8)
-#define CPU_65C02_EA_X (-7)
-#define CPU_65C02_EA_Y (-6)
-#define CPU_65C02_EA_S (-5)
-#define CPU_65C02_EA_P (-4)
+#define CPU_65C02_EA_PC (-8)
+#define CPU_65C02_EA_A (-6)
+#define CPU_65C02_EA_X (-5)
+#define CPU_65C02_EA_Y (-4)
+#define CPU_65C02_EA_S (-3)
+#define CPU_65C02_EA_P (-2)
+#define CPU_65C02_EA_IFLAGS (-1)
 
 // registers, in same order as special memory locations, but reversed on
 // big endian hardware where special memory address will be complemented
@@ -35,7 +37,6 @@
 union cpu_65c02_regs {
 #if __BYTE_ORDER == __BIG_ENDIAN
   struct {
-    uint16_t _fill_pc;
     uint8_t _fill_iflags : 4;
     uint8_t stp_flag : 1;
     uint8_t wai_flag : 1;
@@ -53,28 +54,30 @@ union cpu_65c02_regs {
     uint8_t _fill_y;
     uint8_t _fill_x;
     uint8_t _fill_a;
+    uint16_t _fill_pc;
   } bit;
   struct {
-    uint16_t _fill_pc;
     uint8_t iflags;
     uint8_t p;
     uint8_t s;
     uint8_t y;
     uint8_t x;
     uint8_t a;
+    uint16_t _fill_pc;
   } byte;
   struct {
-    uint16_t pc;
     uint8_t _fill_iflags;
     uint8_t _fill_p;
     uint8_t _fill_s;
     uint8_t _fill_y;
     uint8_t _fill_x;
     uint8_t _fill_a;
+    uint16_t pc;
   } word;
   uint8_t mem_be[8];
 #else
   struct {
+    uint16_t _fill_pc;
     uint8_t _fill_a;
     uint8_t _fill_x;
     uint8_t _fill_y;
@@ -92,25 +95,24 @@ union cpu_65c02_regs {
     uint8_t wai_flag : 1;
     uint8_t stp_flag : 1;
     uint8_t _fill_iflags : 4;
-    uint16_t _fill_pc;
   } bit;
   struct {
+    uint16_t _fill_pc;
     uint8_t a;
     uint8_t x;
     uint8_t y;
     uint8_t s;
     uint8_t p;
     uint8_t iflags;
-    uint16_t _fill_pc;
   } byte;
   struct {
+    uint16_t pc;
     uint8_t _fill_a;
     uint8_t _fill_x;
     uint8_t _fill_y;
     uint8_t _fill_s;
     uint8_t _fill_p;
     uint8_t _fill_iflags;
-    uint16_t pc;
   } word;
   uint8_t mem_le[8];
 #endif
@@ -529,6 +531,7 @@ void cpu_65c02_init(
   void (*write_byte)(void *context, int addr, int data),
   void *write_byte_context
 );
+void cpu_65c02_reset(struct cpu_65c02 *self);
 void cpu_65c02_execute(struct cpu_65c02 *self);
  
 #endif
index 6e251f4..11aeef6 100644 (file)
--- a/cpu_z80.c
+++ b/cpu_z80.c
@@ -1,3 +1,4 @@
+#include <assert.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
@@ -26,8 +27,62 @@ void cpu_z80_init(
   self->out_byte_context = out_byte_context;
 }
 
+void cpu_z80_reset(struct cpu_z80 *self) {
+  self->regs.word.pc = CPU_Z80_RESET_ADDR;
+  self->regs.word.af = 0xffff;
+  self->regs.word.sp = 0xffff;
+  self->regs.word.iflags = 0;
+}
+
 // instruction decode
 void cpu_z80_execute(struct cpu_z80 *self) {
+  if (self->regs.bit.nmi_pending) {
+    self->regs.bit.nmi_pending = false;
+
+    self->regs.word.pc += self->regs.bit.halt_flag;
+    self->regs.bit.halt_flag = false;
+
+    self->regs.bit.iff1 = false;
+    cpu_z80_call(self, true, CPU_Z80_NMI_ADDR);
+    return;
+  }
+
+  if (
+    self->regs.bit.irq_pending &&
+    self->regs.bit.iff1 &&
+    !self->regs.bit.ei_flag
+  ) {
+    self->regs.bit.irq_pending = false;
+
+    self->regs.word.pc += self->regs.bit.halt_flag;
+    self->regs.bit.halt_flag = false;
+
+    self->regs.bit.iff1 = false;
+    self->regs.bit.iff2 = false;
+    switch (self->regs.bit.im) {
+    case 0:
+      // self->regs.byte.v contains the opcode placed on bus by peripheral
+      // only RST instructions are supported at the moment (systems with
+      // 8259 / 8228 could also use CALL, that would be extra complexity)
+      assert((self->regs.byte.v & 0xc7) == 0xc7);
+      cpu_z80_call(self, true, self->regs.byte.v & 0x38);
+      break;
+    case 1:
+      cpu_z80_call(self, true, CPU_Z80_IRQ_ADDR);
+      break;
+    case 2:
+      // self->regs.byte.v contains the vector placed on bus by peripheral
+      // it is combined with self->regs.byte.i to create vector word "iv"
+      cpu_z80_call(self, true, cpu_z80_read_word(self, self->regs.word.iv & 0xfffe));
+      break;
+    default:
+      abort();
+    } 
+    return;
+  }
+
+  self->regs.bit.halt_flag = false;
+  self->regs.bit.ei_flag = false;
   switch (cpu_z80_fetch_byte(self)) {
   case 0x00:
     cpu_z80_nop(self);
@@ -805,196 +860,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_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x01:
-    cpu_z80_rlc(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x02:
-    cpu_z80_rlc(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x03:
-    cpu_z80_rlc(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x04:
-    cpu_z80_rlc(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x05:
-    cpu_z80_rlc(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x06:
-    cpu_z80_rlc(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x07:
-    cpu_z80_rlc(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x08:
-    cpu_z80_rrc(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x09:
-    cpu_z80_rrc(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x0a:
-    cpu_z80_rrc(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x0b:
-    cpu_z80_rrc(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x0c:
-    cpu_z80_rrc(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x0d:
-    cpu_z80_rrc(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x0e:
-    cpu_z80_rrc(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x0f:
-    cpu_z80_rrc(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x10:
-    cpu_z80_rl(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x11:
-    cpu_z80_rl(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x12:
-    cpu_z80_rl(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x13:
-    cpu_z80_rl(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x14:
-    cpu_z80_rl(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x15:
-    cpu_z80_rl(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x16:
-    cpu_z80_rl(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x17:
-    cpu_z80_rl(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x18:
-    cpu_z80_rr(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x19:
-    cpu_z80_rr(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x1a:
-    cpu_z80_rr(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x1b:
-    cpu_z80_rr(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x1c:
-    cpu_z80_rr(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x1d:
-    cpu_z80_rr(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x1e:
-    cpu_z80_rr(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x1f:
-    cpu_z80_rr(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x20:
-    cpu_z80_sla(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x21:
-    cpu_z80_sla(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x22:
-    cpu_z80_sla(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x23:
-    cpu_z80_sla(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x24:
-    cpu_z80_sla(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x25:
-    cpu_z80_sla(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x26:
-    cpu_z80_sla(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x27:
-    cpu_z80_sla(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x28:
-    cpu_z80_sra(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x29:
-    cpu_z80_sra(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x2a:
-    cpu_z80_sra(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x2b:
-    cpu_z80_sra(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x2c:
-    cpu_z80_sra(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x2d:
-    cpu_z80_sra(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x2e:
-    cpu_z80_sra(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x2f:
-    cpu_z80_sra(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x30:
-    cpu_z80_sll(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x31:
-    cpu_z80_sll(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x32:
-    cpu_z80_sll(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x33:
-    cpu_z80_sll(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x34:
-    cpu_z80_sll(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x35:
-    cpu_z80_sll(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x36:
-    cpu_z80_sll(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x37:
-    cpu_z80_sll(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x38:
-    cpu_z80_srl(self, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x39:
-    cpu_z80_srl(self, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x3a:
-    cpu_z80_srl(self, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x3b:
-    cpu_z80_srl(self, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x3c:
-    cpu_z80_srl(self, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x3d:
-    cpu_z80_srl(self, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x3e:
-    cpu_z80_srl(self, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x3f:
-    cpu_z80_srl(self, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x40:
     cpu_z80_bit(self, 0, self->regs.byte.b);
@@ -1189,388 +1244,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_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x81:
-    cpu_z80_res(self, 0, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x82:
-    cpu_z80_res(self, 0, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x83:
-    cpu_z80_res(self, 0, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x84:
-    cpu_z80_res(self, 0, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x85:
-    cpu_z80_res(self, 0, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x86:
-    cpu_z80_res(self, 0, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x87:
-    cpu_z80_res(self, 0, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x88:
-    cpu_z80_res(self, 1, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x89:
-    cpu_z80_res(self, 1, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x8a:
-    cpu_z80_res(self, 1, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x8b:
-    cpu_z80_res(self, 1, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x8c:
-    cpu_z80_res(self, 1, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x8d:
-    cpu_z80_res(self, 1, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x8e:
-    cpu_z80_res(self, 1, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x8f:
-    cpu_z80_res(self, 1, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x90:
-    cpu_z80_res(self, 2, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x91:
-    cpu_z80_res(self, 2, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x92:
-    cpu_z80_res(self, 2, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x93:
-    cpu_z80_res(self, 2, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x94:
-    cpu_z80_res(self, 2, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x95:
-    cpu_z80_res(self, 2, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x96:
-    cpu_z80_res(self, 2, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x97:
-    cpu_z80_res(self, 2, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0x98:
-    cpu_z80_res(self, 3, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0x99:
-    cpu_z80_res(self, 3, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0x9a:
-    cpu_z80_res(self, 3, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0x9b:
-    cpu_z80_res(self, 3, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0x9c:
-    cpu_z80_res(self, 3, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0x9d:
-    cpu_z80_res(self, 3, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0x9e:
-    cpu_z80_res(self, 3, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0x9f:
-    cpu_z80_res(self, 3, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xa0:
-    cpu_z80_res(self, 4, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xa1:
-    cpu_z80_res(self, 4, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xa2:
-    cpu_z80_res(self, 4, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xa3:
-    cpu_z80_res(self, 4, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xa4:
-    cpu_z80_res(self, 4, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xa5:
-    cpu_z80_res(self, 4, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xa6:
-    cpu_z80_res(self, 4, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xa7:
-    cpu_z80_res(self, 4, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xa8:
-    cpu_z80_res(self, 5, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xa9:
-    cpu_z80_res(self, 5, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xaa:
-    cpu_z80_res(self, 5, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xab:
-    cpu_z80_res(self, 5, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xac:
-    cpu_z80_res(self, 5, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xad:
-    cpu_z80_res(self, 5, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xae:
-    cpu_z80_res(self, 5, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xaf:
-    cpu_z80_res(self, 5, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xb0:
-    cpu_z80_res(self, 6, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xb1:
-    cpu_z80_res(self, 6, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xb2:
-    cpu_z80_res(self, 6, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xb3:
-    cpu_z80_res(self, 6, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xb4:
-    cpu_z80_res(self, 6, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xb5:
-    cpu_z80_res(self, 6, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xb6:
-    cpu_z80_res(self, 6, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xb7:
-    cpu_z80_res(self, 6, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xb8:
-    cpu_z80_res(self, 7, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xb9:
-    cpu_z80_res(self, 7, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xba:
-    cpu_z80_res(self, 7, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xbb:
-    cpu_z80_res(self, 7, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xbc:
-    cpu_z80_res(self, 7, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xbd:
-    cpu_z80_res(self, 7, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xbe:
-    cpu_z80_res(self, 7, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xbf:
-    cpu_z80_res(self, 7, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xc0:
-    cpu_z80_set(self, 0, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xc1:
-    cpu_z80_set(self, 0, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xc2:
-    cpu_z80_set(self, 0, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xc3:
-    cpu_z80_set(self, 0, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xc4:
-    cpu_z80_set(self, 0, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xc5:
-    cpu_z80_set(self, 0, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xc6:
-    cpu_z80_set(self, 0, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xc7:
-    cpu_z80_set(self, 0, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xc8:
-    cpu_z80_set(self, 1, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xc9:
-    cpu_z80_set(self, 1, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xca:
-    cpu_z80_set(self, 1, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xcb:
-    cpu_z80_set(self, 1, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xcc:
-    cpu_z80_set(self, 1, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xcd:
-    cpu_z80_set(self, 1, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xce:
-    cpu_z80_set(self, 1, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xcf:
-    cpu_z80_set(self, 1, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xd0:
-    cpu_z80_set(self, 2, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xd1:
-    cpu_z80_set(self, 2, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xd2:
-    cpu_z80_set(self, 2, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xd3:
-    cpu_z80_set(self, 2, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xd4:
-    cpu_z80_set(self, 2, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xd5:
-    cpu_z80_set(self, 2, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xd6:
-    cpu_z80_set(self, 2, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xd7:
-    cpu_z80_set(self, 2, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xd8:
-    cpu_z80_set(self, 3, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xd9:
-    cpu_z80_set(self, 3, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xda:
-    cpu_z80_set(self, 3, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xdb:
-    cpu_z80_set(self, 3, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xdc:
-    cpu_z80_set(self, 3, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xdd:
-    cpu_z80_set(self, 3, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xde:
-    cpu_z80_set(self, 3, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xdf:
-    cpu_z80_set(self, 3, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xe0:
-    cpu_z80_set(self, 4, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xe1:
-    cpu_z80_set(self, 4, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xe2:
-    cpu_z80_set(self, 4, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xe3:
-    cpu_z80_set(self, 4, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xe4:
-    cpu_z80_set(self, 4, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xe5:
-    cpu_z80_set(self, 4, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xe6:
-    cpu_z80_set(self, 4, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xe7:
-    cpu_z80_set(self, 4, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xe8:
-    cpu_z80_set(self, 5, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xe9:
-    cpu_z80_set(self, 5, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xea:
-    cpu_z80_set(self, 5, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xeb:
-    cpu_z80_set(self, 5, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xec:
-    cpu_z80_set(self, 5, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xed:
-    cpu_z80_set(self, 5, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xee:
-    cpu_z80_set(self, 5, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xef:
-    cpu_z80_set(self, 5, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xf0:
-    cpu_z80_set(self, 6, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xf1:
-    cpu_z80_set(self, 6, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xf2:
-    cpu_z80_set(self, 6, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xf3:
-    cpu_z80_set(self, 6, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xf4:
-    cpu_z80_set(self, 6, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xf5:
-    cpu_z80_set(self, 6, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xf6:
-    cpu_z80_set(self, 6, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xf7:
-    cpu_z80_set(self, 6, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   case 0xf8:
-    cpu_z80_set(self, 7, CPU_Z80_EA_B, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_B, CPU_Z80_EA_SINK);
     break;
   case 0xf9:
-    cpu_z80_set(self, 7, CPU_Z80_EA_C, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_C, CPU_Z80_EA_SINK);
     break;
   case 0xfa:
-    cpu_z80_set(self, 7, CPU_Z80_EA_D, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_D, CPU_Z80_EA_SINK);
     break;
   case 0xfb:
-    cpu_z80_set(self, 7, CPU_Z80_EA_E, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_E, CPU_Z80_EA_SINK);
     break;
   case 0xfc:
-    cpu_z80_set(self, 7, CPU_Z80_EA_H, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_H, CPU_Z80_EA_SINK);
     break;
   case 0xfd:
-    cpu_z80_set(self, 7, CPU_Z80_EA_L, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_L, CPU_Z80_EA_SINK);
     break;
   case 0xfe:
-    cpu_z80_set(self, 7, self->regs.word.hl, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, self->regs.word.hl, CPU_Z80_EA_SINK);
     break;
   case 0xff:
-    cpu_z80_set(self, 7, CPU_Z80_EA_A, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, CPU_Z80_EA_A, CPU_Z80_EA_SINK);
     break;
   }
 }
@@ -2375,7 +2430,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_rlc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x06:
-    cpu_z80_rlc(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x07:
     cpu_z80_rlc(self, ea, CPU_Z80_EA_A);
@@ -2399,7 +2454,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_rrc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x0e:
-    cpu_z80_rrc(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x0f:
     cpu_z80_rrc(self, ea, CPU_Z80_EA_A);
@@ -2423,7 +2478,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_rl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x16:
-    cpu_z80_rl(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x17:
     cpu_z80_rl(self, ea, CPU_Z80_EA_A);
@@ -2447,7 +2502,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_rr(self, ea, CPU_Z80_EA_L);
     break;
   case 0x1e:
-    cpu_z80_rr(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x1f:
     cpu_z80_rr(self, ea, CPU_Z80_EA_A);
@@ -2471,7 +2526,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_sla(self, ea, CPU_Z80_EA_L);
     break;
   case 0x26:
-    cpu_z80_sla(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x27:
     cpu_z80_sla(self, ea, CPU_Z80_EA_A);
@@ -2495,7 +2550,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_sra(self, ea, CPU_Z80_EA_L);
     break;
   case 0x2e:
-    cpu_z80_sra(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x2f:
     cpu_z80_sra(self, ea, CPU_Z80_EA_A);
@@ -2519,7 +2574,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_sll(self, ea, CPU_Z80_EA_L);
     break;
   case 0x36:
-    cpu_z80_sll(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x37:
     cpu_z80_sll(self, ea, CPU_Z80_EA_A);
@@ -2543,7 +2598,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_srl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x3e:
-    cpu_z80_srl(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x3f:
     cpu_z80_srl(self, ea, CPU_Z80_EA_A);
@@ -2759,7 +2814,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0x86:
-    cpu_z80_res(self, 0, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_SINK);
     break;
   case 0x87:
     cpu_z80_res(self, 0, ea, CPU_Z80_EA_A);
@@ -2783,7 +2838,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0x8e:
-    cpu_z80_res(self, 1, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_SINK);
     break;
   case 0x8f:
     cpu_z80_res(self, 1, ea, CPU_Z80_EA_A);
@@ -2807,7 +2862,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0x96:
-    cpu_z80_res(self, 2, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_SINK);
     break;
   case 0x97:
     cpu_z80_res(self, 2, ea, CPU_Z80_EA_A);
@@ -2831,7 +2886,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0x9e:
-    cpu_z80_res(self, 3, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_SINK);
     break;
   case 0x9f:
     cpu_z80_res(self, 3, ea, CPU_Z80_EA_A);
@@ -2855,7 +2910,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xa6:
-    cpu_z80_res(self, 4, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_SINK);
     break;
   case 0xa7:
     cpu_z80_res(self, 4, ea, CPU_Z80_EA_A);
@@ -2879,7 +2934,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xae:
-    cpu_z80_res(self, 5, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_SINK);
     break;
   case 0xaf:
     cpu_z80_res(self, 5, ea, CPU_Z80_EA_A);
@@ -2903,7 +2958,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xb6:
-    cpu_z80_res(self, 6, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_SINK);
     break;
   case 0xb7:
     cpu_z80_res(self, 6, ea, CPU_Z80_EA_A);
@@ -2927,7 +2982,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xbe:
-    cpu_z80_res(self, 7, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_SINK);
     break;
   case 0xbf:
     cpu_z80_res(self, 7, ea, CPU_Z80_EA_A);
@@ -2951,7 +3006,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0xc6:
-    cpu_z80_set(self, 0, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_SINK);
     break;
   case 0xc7:
     cpu_z80_set(self, 0, ea, CPU_Z80_EA_A);
@@ -2975,7 +3030,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0xce:
-    cpu_z80_set(self, 1, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_SINK);
     break;
   case 0xcf:
     cpu_z80_set(self, 1, ea, CPU_Z80_EA_A);
@@ -2999,7 +3054,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0xd6:
-    cpu_z80_set(self, 2, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_SINK);
     break;
   case 0xd7:
     cpu_z80_set(self, 2, ea, CPU_Z80_EA_A);
@@ -3023,7 +3078,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0xde:
-    cpu_z80_set(self, 3, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_SINK);
     break;
   case 0xdf:
     cpu_z80_set(self, 3, ea, CPU_Z80_EA_A);
@@ -3047,7 +3102,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xe6:
-    cpu_z80_set(self, 4, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_SINK);
     break;
   case 0xe7:
     cpu_z80_set(self, 4, ea, CPU_Z80_EA_A);
@@ -3071,7 +3126,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xee:
-    cpu_z80_set(self, 5, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_SINK);
     break;
   case 0xef:
     cpu_z80_set(self, 5, ea, CPU_Z80_EA_A);
@@ -3095,7 +3150,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xf6:
-    cpu_z80_set(self, 6, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_SINK);
     break;
   case 0xf7:
     cpu_z80_set(self, 6, ea, CPU_Z80_EA_A);
@@ -3119,7 +3174,7 @@ void cpu_z80_execute_dd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xfe:
-    cpu_z80_set(self, 7, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_SINK);
     break;
   case 0xff:
     cpu_z80_set(self, 7, ea, CPU_Z80_EA_A);
@@ -3466,7 +3521,7 @@ void cpu_z80_execute_ed(struct cpu_z80 *self) {
     cpu_z80_rld(self);
     break;
   case 0x70:
-    cpu_z80_in_test(self, CPU_Z80_EA_NONE, cpu_z80_in_byte(self, self->regs.word.bc));
+    cpu_z80_in_test(self, CPU_Z80_EA_SINK, cpu_z80_in_byte(self, self->regs.word.bc));
     break;
   case 0x71:
     cpu_z80_out(self, self->regs.word.bc, 0);
@@ -4700,7 +4755,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_rlc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x06:
-    cpu_z80_rlc(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rlc(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x07:
     cpu_z80_rlc(self, ea, CPU_Z80_EA_A);
@@ -4724,7 +4779,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_rrc(self, ea, CPU_Z80_EA_L);
     break;
   case 0x0e:
-    cpu_z80_rrc(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rrc(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x0f:
     cpu_z80_rrc(self, ea, CPU_Z80_EA_A);
@@ -4748,7 +4803,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_rl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x16:
-    cpu_z80_rl(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rl(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x17:
     cpu_z80_rl(self, ea, CPU_Z80_EA_A);
@@ -4772,7 +4827,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_rr(self, ea, CPU_Z80_EA_L);
     break;
   case 0x1e:
-    cpu_z80_rr(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_rr(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x1f:
     cpu_z80_rr(self, ea, CPU_Z80_EA_A);
@@ -4796,7 +4851,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_sla(self, ea, CPU_Z80_EA_L);
     break;
   case 0x26:
-    cpu_z80_sla(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_sla(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x27:
     cpu_z80_sla(self, ea, CPU_Z80_EA_A);
@@ -4820,7 +4875,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_sra(self, ea, CPU_Z80_EA_L);
     break;
   case 0x2e:
-    cpu_z80_sra(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_sra(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x2f:
     cpu_z80_sra(self, ea, CPU_Z80_EA_A);
@@ -4844,7 +4899,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_sll(self, ea, CPU_Z80_EA_L);
     break;
   case 0x36:
-    cpu_z80_sll(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_sll(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x37:
     cpu_z80_sll(self, ea, CPU_Z80_EA_A);
@@ -4868,7 +4923,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_srl(self, ea, CPU_Z80_EA_L);
     break;
   case 0x3e:
-    cpu_z80_srl(self, ea, CPU_Z80_EA_NONE);
+    cpu_z80_srl(self, ea, CPU_Z80_EA_SINK);
     break;
   case 0x3f:
     cpu_z80_srl(self, ea, CPU_Z80_EA_A);
@@ -5084,7 +5139,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0x86:
-    cpu_z80_res(self, 0, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 0, ea, CPU_Z80_EA_SINK);
     break;
   case 0x87:
     cpu_z80_res(self, 0, ea, CPU_Z80_EA_A);
@@ -5108,7 +5163,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0x8e:
-    cpu_z80_res(self, 1, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 1, ea, CPU_Z80_EA_SINK);
     break;
   case 0x8f:
     cpu_z80_res(self, 1, ea, CPU_Z80_EA_A);
@@ -5132,7 +5187,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0x96:
-    cpu_z80_res(self, 2, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 2, ea, CPU_Z80_EA_SINK);
     break;
   case 0x97:
     cpu_z80_res(self, 2, ea, CPU_Z80_EA_A);
@@ -5156,7 +5211,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0x9e:
-    cpu_z80_res(self, 3, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 3, ea, CPU_Z80_EA_SINK);
     break;
   case 0x9f:
     cpu_z80_res(self, 3, ea, CPU_Z80_EA_A);
@@ -5180,7 +5235,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xa6:
-    cpu_z80_res(self, 4, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 4, ea, CPU_Z80_EA_SINK);
     break;
   case 0xa7:
     cpu_z80_res(self, 4, ea, CPU_Z80_EA_A);
@@ -5204,7 +5259,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xae:
-    cpu_z80_res(self, 5, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 5, ea, CPU_Z80_EA_SINK);
     break;
   case 0xaf:
     cpu_z80_res(self, 5, ea, CPU_Z80_EA_A);
@@ -5228,7 +5283,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xb6:
-    cpu_z80_res(self, 6, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 6, ea, CPU_Z80_EA_SINK);
     break;
   case 0xb7:
     cpu_z80_res(self, 6, ea, CPU_Z80_EA_A);
@@ -5252,7 +5307,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_res(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xbe:
-    cpu_z80_res(self, 7, ea, CPU_Z80_EA_NONE);
+    cpu_z80_res(self, 7, ea, CPU_Z80_EA_SINK);
     break;
   case 0xbf:
     cpu_z80_res(self, 7, ea, CPU_Z80_EA_A);
@@ -5276,7 +5331,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 0, ea, CPU_Z80_EA_L);
     break;
   case 0xc6:
-    cpu_z80_set(self, 0, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 0, ea, CPU_Z80_EA_SINK);
     break;
   case 0xc7:
     cpu_z80_set(self, 0, ea, CPU_Z80_EA_A);
@@ -5300,7 +5355,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 1, ea, CPU_Z80_EA_L);
     break;
   case 0xce:
-    cpu_z80_set(self, 1, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 1, ea, CPU_Z80_EA_SINK);
     break;
   case 0xcf:
     cpu_z80_set(self, 1, ea, CPU_Z80_EA_A);
@@ -5324,7 +5379,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 2, ea, CPU_Z80_EA_L);
     break;
   case 0xd6:
-    cpu_z80_set(self, 2, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 2, ea, CPU_Z80_EA_SINK);
     break;
   case 0xd7:
     cpu_z80_set(self, 2, ea, CPU_Z80_EA_A);
@@ -5348,7 +5403,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 3, ea, CPU_Z80_EA_L);
     break;
   case 0xde:
-    cpu_z80_set(self, 3, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 3, ea, CPU_Z80_EA_SINK);
     break;
   case 0xdf:
     cpu_z80_set(self, 3, ea, CPU_Z80_EA_A);
@@ -5372,7 +5427,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 4, ea, CPU_Z80_EA_L);
     break;
   case 0xe6:
-    cpu_z80_set(self, 4, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 4, ea, CPU_Z80_EA_SINK);
     break;
   case 0xe7:
     cpu_z80_set(self, 4, ea, CPU_Z80_EA_A);
@@ -5396,7 +5451,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 5, ea, CPU_Z80_EA_L);
     break;
   case 0xee:
-    cpu_z80_set(self, 5, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 5, ea, CPU_Z80_EA_SINK);
     break;
   case 0xef:
     cpu_z80_set(self, 5, ea, CPU_Z80_EA_A);
@@ -5420,7 +5475,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 6, ea, CPU_Z80_EA_L);
     break;
   case 0xf6:
-    cpu_z80_set(self, 6, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 6, ea, CPU_Z80_EA_SINK);
     break;
   case 0xf7:
     cpu_z80_set(self, 6, ea, CPU_Z80_EA_A);
@@ -5444,7 +5499,7 @@ void cpu_z80_execute_fd_cb(struct cpu_z80 *self) {
     cpu_z80_set(self, 7, ea, CPU_Z80_EA_L);
     break;
   case 0xfe:
-    cpu_z80_set(self, 7, ea, CPU_Z80_EA_NONE);
+    cpu_z80_set(self, 7, ea, CPU_Z80_EA_SINK);
     break;
   case 0xff:
     cpu_z80_set(self, 7, ea, CPU_Z80_EA_A);
index be7d978..b5b4c2e 100644 (file)
--- a/cpu_z80.h
+++ b/cpu_z80.h
 #define ALWAYS_INLINE __attribute__((always_inline))
 #endif
 
+#define CPU_Z80_NMI_ADDR 0x66
+#define CPU_Z80_RESET_ADDR 0
+#define CPU_Z80_IRQ_ADDR 0x38
+
 // bits within REG_F
 #define CPU_Z80_REG_F_BIT_C 0
 #define CPU_Z80_REG_F_BIT_N 1
 #define CPU_Z80_REG_F_BIT_S 7
 
 // special memory locations (negative address)
-// note: CPU_Z80_EA_NONE is a byte-wide sink for implmenting "in f,(c)" and
-// DDCB/FDCB undocumented instructions, to store into and never read back
+// note: CPU_Z80_EA_SINK is a byte-wide sink for implementing the "in f,(c)"
+// and DDCB/FDCB undocumented instructions, to store into and never read back
+#define CPU_Z80_EA_PC (-0x1e)
+#define CPU_Z80_EA_AF (-0x1c)
+#define CPU_Z80_EA_BC (-0x1a)
+#define CPU_Z80_EA_DE (-0x18)
+#define CPU_Z80_EA_HL (-0x16)
+#define CPU_Z80_EA_SP (-0x14)
+#define CPU_Z80_EA_IX (-0x12)
+#define CPU_Z80_EA_IY (-0x10)
+#define CPU_Z80_EA_AF_PRIME (-0xe)
+#define CPU_Z80_EA_BC_PRIME (-0xc)
+#define CPU_Z80_EA_DE_PRIME (-0xa)
+#define CPU_Z80_EA_HL_PRIME (-8)
+#define CPU_Z80_EA_IFLAGS (-6)
+#define CPU_Z80_EA_IV (-4)
+
+// pc (-0x1e)
 #define CPU_Z80_EA_F (-0x1c)
 #define CPU_Z80_EA_A (-0x1b)
 #define CPU_Z80_EA_C (-0x1a)
 #define CPU_Z80_EA_D (-0x17)
 #define CPU_Z80_EA_L (-0x16)
 #define CPU_Z80_EA_H (-0x15)
+// sp (-0x14)
 #define CPU_Z80_EA_IXL (-0x12)
 #define CPU_Z80_EA_IXH (-0x11)
 #define CPU_Z80_EA_IYL (-0x10)
 #define CPU_Z80_EA_IYH (-0xf)
-#define CPU_Z80_EA_I (-0xe)
-#define CPU_Z80_EA_R (-0xd)
-
-#define CPU_Z80_EA_AF (-0x1c)
-#define CPU_Z80_EA_BC (-0x1a)
-#define CPU_Z80_EA_DE (-0x18)
-#define CPU_Z80_EA_HL (-0x16)
-#define CPU_Z80_EA_SP (-0x14)
-#define CPU_Z80_EA_IX (-0x12)
-#define CPU_Z80_EA_IY (-0x10)
-#define CPU_Z80_EA_AF_PRIME (-0xc)
-#define CPU_Z80_EA_BC_PRIME (-0xa)
-#define CPU_Z80_EA_DE_PRIME (-8)
-#define CPU_Z80_EA_HL_PRIME (-6)
-#define CPU_Z80_EA_PC (-4)
-#define CPU_Z80_EA_INTF (-2)
-#define CPU_Z80_EA_NONE (-1)
+// af_prime (-0xe)
+// bc_prime (-0xc)
+// de_prime (-0xa)
+// hl_prime (-8)
+// iflags (-6)
+#define CPU_Z80_EA_V (-4)
+#define CPU_Z80_EA_I (-3)
+#define CPU_Z80_EA_R (-2)
+#define CPU_Z80_EA_SINK (-1)
 
 // registers, in same order as special memory locations, but reversed on
 // big endian hardware where special memory address will be complemented
 union cpu_z80_regs {
 #if __BYTE_ORDER == __BIG_ENDIAN
   struct {
-    uint8_t _fill_none;
-    uint8_t _fill_intf : 4;
-    uint8_t iff2 : 1;
-    uint8_t iff1 : 1;
-    uint8_t im : 2;
-    uint16_t _fill_pc;
+    uint8_t _fill_sink;
+    uint8_t _fill_r;
+    uint16_t _fill_iv;
+    uint16_t _fill_iflags : 7;
+    uint16_t reti_flag : 1;
+    uint16_t ei_flag : 1;
+    uint16_t halt_flag : 1;
+    uint16_t nmi_pending : 1;
+    uint16_t irq_pending : 1;
+    uint16_t iff2 : 1;
+    uint16_t iff1 : 1;
+    uint16_t im : 2;
     uint16_t _fill_hl_prime;
     uint16_t _fill_de_prime;
     uint16_t _fill_bc_prime;
     uint16_t _fill_af_prime;
-    uint8_t _fill_r;
-    uint8_t _fill_i;
     uint16_t _fill_iy;
     uint16_t _fill_ix;
     uint16_t _fill_sp;
@@ -84,11 +101,14 @@ union cpu_z80_regs {
     uint8_t pvf: 1;
     uint8_t nf : 1;
     uint8_t cf : 1;
+    uint16_t _fill_pc;
   } bit;
   struct {
-    uint8_t _fill_none;
-    uint8_t _fill_intf;
-    uint16_t _fill_pc;
+    uint8_t sink;
+    uint8_t r;
+    uint8_t i;
+    uint8_t v;
+    uint16_t _fill_iflags;
     uint16_t _fill_hl_prime;
     uint16_t _fill_de_prime;
     uint16_t _fill_bc_prime;
@@ -108,17 +128,17 @@ union cpu_z80_regs {
     uint8_t c;
     uint8_t a;
     uint8_t f;
+    uint16_t _fill_pc;
   } byte;
   struct {
-    uint8_t _fill_none;
-    uint8_t _fill_intf;
-    uint16_t pc;
+    uint8_t _fill_sink;
+    uint8_t _fill_r;
+    uint16_t iv;
+    uint16_t iflags;
     uint16_t hl_prime;
     uint16_t de_prime;
     uint16_t bc_prime;
     uint16_t af_prime;
-    uint8_t _fill_r;
-    uint8_t _fill_i;
     uint16_t iy;
     uint16_t ix;
     uint16_t sp;
@@ -126,10 +146,12 @@ union cpu_z80_regs {
     uint16_t de;
     uint16_t bc;
     uint16_t af;
+    uint16_t pc;
   } word;
-  uint8_t mem_be[0x1c];
+  uint8_t mem_be[0x1e];
 #else
   struct {
+    uint16_t _fill_pc;
     uint8_t cf : 1;
     uint8_t nf : 1;
     uint8_t pvf: 1;
@@ -145,20 +167,25 @@ union cpu_z80_regs {
     uint16_t _fill_sp;
     uint16_t _fill_ix;
     uint16_t _fill_iy;
-    uint8_t _fill_i;
-    uint8_t _fill_r;
     uint16_t _fill_af_prime;
     uint16_t _fill_bc_prime;
     uint16_t _fill_de_prime;
     uint16_t _fill_hl_prime;
-    uint16_t _fill_pc;
-    uint8_t im : 2;
-    uint8_t iff1 : 1;
-    uint8_t iff2 : 1;
-    uint8_t _fill_intf : 4;
-    uint8_t _fill_none;
+    uint16_t im : 2;
+    uint16_t iff1 : 1;
+    uint16_t iff2 : 1;
+    uint16_t irq_pending : 1;
+    uint16_t nmi_pending : 1;
+    uint16_t halt_flag : 1;
+    uint16_t ei_flag : 1;
+    uint16_t reti_flag : 1;
+    uint16_t _fill_iflags : 7;
+    uint16_t _fill_iv;
+    uint8_t _fill_r;
+    uint8_t _fill_sink;
   } bit;
   struct {
+    uint16_t _fill_pc;
     uint8_t f;
     uint8_t a;
     uint8_t c;
@@ -172,17 +199,18 @@ union cpu_z80_regs {
     uint8_t ixh;
     uint8_t iyl;
     uint8_t iyh;
-    uint8_t i;
-    uint8_t r;
     uint16_t _fill_af_prime;
     uint16_t _fill_bc_prime;
     uint16_t _fill_de_prime;
     uint16_t _fill_hl_prime;
-    uint16_t _fill_pc;
-    uint8_t _fill_intf;
-    uint8_t _fill_none;
+    uint16_t _fill_iflags;
+    uint8_t v;
+    uint8_t i;
+    uint8_t r;
+    uint8_t sink;
   } byte;
   struct {
+    uint16_t pc;
     uint16_t af;
     uint16_t bc;
     uint16_t de;
@@ -190,17 +218,16 @@ union cpu_z80_regs {
     uint16_t sp;
     uint16_t ix;
     uint16_t iy;
-    uint8_t _fill_i;
-    uint8_t _fill_r;
     uint16_t af_prime;
     uint16_t bc_prime;
     uint16_t de_prime;
     uint16_t hl_prime;
-    uint16_t pc;
-    uint8_t _fill_intf;
-    uint8_t _fill_none;
+    uint16_t iflags;
+    uint16_t iv;
+    uint8_t _fill_r;
+    uint8_t _fill_sink;
   } word;
-  uint8_t mem_le[0x1c];
+  uint8_t mem_le[0x1e];
 #endif
 };
 
@@ -585,6 +612,7 @@ static ALWAYS_INLINE void cpu_z80_dec_word(struct cpu_z80 *self, int lvalue) {
 
 static ALWAYS_INLINE void cpu_z80_di(struct cpu_z80 *self) {
   self->regs.bit.iff1 = false;
+  self->regs.bit.iff2 = false;
 }
 
 static ALWAYS_INLINE void cpu_z80_djnz(struct cpu_z80 *self, int rvalue) {
@@ -594,6 +622,8 @@ static ALWAYS_INLINE void cpu_z80_djnz(struct cpu_z80 *self, int rvalue) {
 
 static ALWAYS_INLINE void cpu_z80_ei(struct cpu_z80 *self) {
   self->regs.bit.iff1 = true;
+  self->regs.bit.iff2 = true;
+  self->regs.bit.ei_flag = true; // causes one-cycle interrupt delay
 }
 
 static ALWAYS_INLINE void cpu_z80_ex(struct cpu_z80 *self, int lvalue0, int lvalue1) {
@@ -604,7 +634,8 @@ static ALWAYS_INLINE void cpu_z80_ex(struct cpu_z80 *self, int lvalue0, int lval
 }
 
 static ALWAYS_INLINE void cpu_z80_halt(struct cpu_z80 *self) {
-  abort();
+  self->regs.bit.halt_flag = true;
+  --self->regs.word.pc;
 }
 
 static ALWAYS_INLINE void cpu_z80_ill(struct cpu_z80 *self) {
@@ -816,7 +847,7 @@ static ALWAYS_INLINE void cpu_z80_ret(struct cpu_z80 *self, bool pred) {
 }
 
 static ALWAYS_INLINE void cpu_z80_reti(struct cpu_z80 *self) {
-  self->regs.bit.iff1 = self->regs.bit.iff2;
+  self->regs.bit.reti_flag = true;
   self->regs.word.pc = cpu_z80_pop_word(self);
 }
 
@@ -1167,6 +1198,7 @@ void cpu_z80_init(
   void (*out_byte)(void *context, int addr, int data),
   void *out_byte_context
 );
+void cpu_z80_reset(struct cpu_z80 *self);
 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);
index 9fcd053..3a2db5b 100755 (executable)
@@ -268,7 +268,7 @@ for i in range(0x700):
     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')
+      instr.append('CPU_Z80_EA_SINK')
     print(
       '    cpu_z80_{0:s}{1:s}(self{2:s});'.format(
         instr[0],
index fe8bc18..92a217b 100644 (file)
@@ -2,7 +2,7 @@ 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_in_test(self/
 s/cpu_z80_in_test(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)))/cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_port_word(self)))/
-s/cpu_z80_in_test(self, CPU_Z80_EA_F/cpu_z80_in_test(self, CPU_Z80_EA_NONE/
+s/cpu_z80_in_test(self, CPU_Z80_EA_F/cpu_z80_in_test(self, CPU_Z80_EA_SINK/
 s/cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs\.byte\.a)/cpu_z80_out(self, cpu_z80_port_word(self), self->regs.byte.a)/
 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);/
index 583865d..c9134e2 100644 (file)
@@ -206,8 +206,9 @@ int main(int argc, char **argv) {
 #else
   struct cpu_65c02 cpu;
   cpu_65c02_init(&cpu, read_byte, NULL, write_byte, NULL);
-  cpu.regs.byte.s = 0xff;
+  cpu_65c02_reset(&cpu);
   cpu.regs.word.pc = entry_point;
+  cpu.regs.byte.s = 0xff;
 
   while (true) {
 #if REG_TRACE
index 2913ae1..7b3b05e 100644 (file)
--- a/emu_z80.c
+++ b/emu_z80.c
@@ -287,8 +287,7 @@ int main(int argc, char **argv) {
     out_byte,
     NULL
   );
-  cpu.regs.word.af = 0xffff;
-  cpu.regs.word.sp = 0xffff;
+  cpu_z80_reset(&cpu);
   cpu.regs.word.pc = entry_point;
 
   while (true) {