auto Z80::instruction() -> void {
  P = 0;

  if(EI) {
    EI = 0;
    IFF1 = 1;
    IFF2 = 1;
  }

  if(HALT) {
    return wait(1);
  }

  uint8 code;
  while(true) {
    R.bit(0,6)++;
    code = opcode();
    if(code == 0xdd) { prefix = Prefix::ix; continue; }
    if(code == 0xfd) { prefix = Prefix::iy; continue; }
    break;
  }

  if(code == 0xcb && prefix != Prefix::hl) {
    WZ = HL + (int8)operand();
    wait(1);
  //R is not incremented here
    instructionCBd(WZ, opcode());
  } else if(code == 0xcb) {
    R.bit(0,6)++;
    instructionCB(opcode());
  } else if(code == 0xed) {
    R.bit(0,6)++;
    instructionED(opcode());
  } else {
    instruction(code);
  }

  prefix = Prefix::hl;
}

#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);

auto Z80::instruction(uint8 code) -> void {
  switch(code) {
  op(0x00, NOP)
  op(0x01, LD_rr_nn, BC)
  op(0x02, LD_irr_a, BC)
  op(0x03, INC_rr, BC)
  op(0x04, INC_r, B)
  op(0x05, DEC_r, B)
  op(0x06, LD_r_n, B)
  op(0x07, RLCA)
  op(0x08, EX_rr_rr, AF, AF_)
  op(0x09, ADD_hl_rr, BC)
  op(0x0a, LD_a_irr, BC)
  op(0x0b, DEC_rr, BC)
  op(0x0c, INC_r, C)
  op(0x0d, DEC_r, C)
  op(0x0e, LD_r_n, C)
  op(0x0f, RRCA)
  op(0x10, DJNZ_e)
  op(0x11, LD_rr_nn, DE)
  op(0x12, LD_irr_a, DE)
  op(0x13, INC_rr, DE)
  op(0x14, INC_r, D)
  op(0x15, DEC_r, D)
  op(0x16, LD_r_n, D)
  op(0x17, RLA)
  op(0x18, JR_c_e, 1)
  op(0x19, ADD_hl_rr, DE)
  op(0x1a, LD_a_irr, DE)
  op(0x1b, DEC_rr, DE)
  op(0x1c, INC_r, E)
  op(0x1d, DEC_r, E)
  op(0x1e, LD_r_n, E)
  op(0x1f, RRA)
  op(0x20, JR_c_e, ZF == 0)
  op(0x21, LD_rr_nn, HL)
  op(0x22, LD_inn_rr, HL)
  op(0x23, INC_rr, HL)
  op(0x24, INC_r, H)
  op(0x25, DEC_r, H)
  op(0x26, LD_r_n, H)
  op(0x27, DAA)
  op(0x28, JR_c_e, ZF == 1)
  op(0x29, ADD_hl_rr, HL)
  op(0x2a, LD_rr_inn, HL)
  op(0x2b, DEC_rr, HL)
  op(0x2c, INC_r, L)
  op(0x2d, DEC_r, L)
  op(0x2e, LD_r_n, L)
  op(0x2f, CPL)
  op(0x30, JR_c_e, CF == 0)
  op(0x31, LD_rr_nn, SP)
  op(0x32, LD_inn_a)
  op(0x33, INC_rr, SP)
  op(0x34, INC_irr, HL)
  op(0x35, DEC_irr, HL)
  op(0x36, LD_irr_n, HL)
  op(0x37, SCF)
  op(0x38, JR_c_e, CF == 1)
  op(0x39, ADD_hl_rr, SP)
  op(0x3a, LD_a_inn)
  op(0x3b, DEC_rr, SP)
  op(0x3c, INC_r, A)
  op(0x3d, DEC_r, A)
  op(0x3e, LD_r_n, A)
  op(0x3f, CCF)
  op(0x40, LD_r_r, B, B)
  op(0x41, LD_r_r, B, C)
  op(0x42, LD_r_r, B, D)
  op(0x43, LD_r_r, B, E)
  op(0x44, LD_r_r, B, H)
  op(0x45, LD_r_r, B, L)
  op(0x46, LD_r_irr, B, HL)
  op(0x47, LD_r_r, B, A)
  op(0x48, LD_r_r, C, B)
  op(0x49, LD_r_r, C, C)
  op(0x4a, LD_r_r, C, D)
  op(0x4b, LD_r_r, C, E)
  op(0x4c, LD_r_r, C, H)
  op(0x4d, LD_r_r, C, L)
  op(0x4e, LD_r_irr, C, HL)
  op(0x4f, LD_r_r, C, A)
  op(0x50, LD_r_r, D, B)
  op(0x51, LD_r_r, D, C)
  op(0x52, LD_r_r, D, D)
  op(0x53, LD_r_r, D, E)
  op(0x54, LD_r_r, D, H)
  op(0x55, LD_r_r, D, L)
  op(0x56, LD_r_irr, D, HL)
  op(0x57, LD_r_r, D, A)
  op(0x58, LD_r_r, E, B)
  op(0x59, LD_r_r, E, C)
  op(0x5a, LD_r_r, E, D)
  op(0x5b, LD_r_r, E, E)
  op(0x5c, LD_r_r, E, H)
  op(0x5d, LD_r_r, E, L)
  op(0x5e, LD_r_irr, E, HL)
  op(0x5f, LD_r_r, E, A)
  op(0x60, LD_r_r, H, B)
  op(0x61, LD_r_r, H, C)
  op(0x62, LD_r_r, H, D)
  op(0x63, LD_r_r, H, E)
  op(0x64, LD_r_r, H, H)
  op(0x65, LD_r_r, H, L)
  op(0x66, LD_r_irr, _H, HL)
  op(0x67, LD_r_r, H, A)
  op(0x68, LD_r_r, L, B)
  op(0x69, LD_r_r, L, C)
  op(0x6a, LD_r_r, L, D)
  op(0x6b, LD_r_r, L, E)
  op(0x6c, LD_r_r, L, H)
  op(0x6d, LD_r_r, L, L)
  op(0x6e, LD_r_irr, _L, HL)
  op(0x6f, LD_r_r, L, A)
  op(0x70, LD_irr_r, HL, B)
  op(0x71, LD_irr_r, HL, C)
  op(0x72, LD_irr_r, HL, D)
  op(0x73, LD_irr_r, HL, E)
  op(0x74, LD_irr_r, HL, _H)
  op(0x75, LD_irr_r, HL, _L)
  op(0x76, HALT)
  op(0x77, LD_irr_r, HL, A)
  op(0x78, LD_r_r, A, B)
  op(0x79, LD_r_r, A, C)
  op(0x7a, LD_r_r, A, D)
  op(0x7b, LD_r_r, A, E)
  op(0x7c, LD_r_r, A, H)
  op(0x7d, LD_r_r, A, L)
  op(0x7e, LD_r_irr, A, HL)
  op(0x7f, LD_r_r, A, A)
  op(0x80, ADD_a_r, B)
  op(0x81, ADD_a_r, C)
  op(0x82, ADD_a_r, D)
  op(0x83, ADD_a_r, E)
  op(0x84, ADD_a_r, H)
  op(0x85, ADD_a_r, L)
  op(0x86, ADD_a_irr, HL)
  op(0x87, ADD_a_r, A)
  op(0x88, ADC_a_r, B)
  op(0x89, ADC_a_r, C)
  op(0x8a, ADC_a_r, D)
  op(0x8b, ADC_a_r, E)
  op(0x8c, ADC_a_r, H)
  op(0x8d, ADC_a_r, L)
  op(0x8e, ADC_a_irr, HL)
  op(0x8f, ADC_a_r, A)
  op(0x90, SUB_a_r, B)
  op(0x91, SUB_a_r, C)
  op(0x92, SUB_a_r, D)
  op(0x93, SUB_a_r, E)
  op(0x94, SUB_a_r, H)
  op(0x95, SUB_a_r, L)
  op(0x96, SUB_a_irr, HL)
  op(0x97, SUB_a_r, A)
  op(0x98, SBC_a_r, B)
  op(0x99, SBC_a_r, C)
  op(0x9a, SBC_a_r, D)
  op(0x9b, SBC_a_r, E)
  op(0x9c, SBC_a_r, H)
  op(0x9d, SBC_a_r, L)
  op(0x9e, SBC_a_irr, HL)
  op(0x9f, SBC_a_r, A)
  op(0xa0, AND_a_r, B)
  op(0xa1, AND_a_r, C)
  op(0xa2, AND_a_r, D)
  op(0xa3, AND_a_r, E)
  op(0xa4, AND_a_r, H)
  op(0xa5, AND_a_r, L)
  op(0xa6, AND_a_irr, HL)
  op(0xa7, AND_a_r, A)
  op(0xa8, XOR_a_r, B)
  op(0xa9, XOR_a_r, C)
  op(0xaa, XOR_a_r, D)
  op(0xab, XOR_a_r, E)
  op(0xac, XOR_a_r, H)
  op(0xad, XOR_a_r, L)
  op(0xae, XOR_a_irr, HL)
  op(0xaf, XOR_a_r, A)
  op(0xb0, OR_a_r, B)
  op(0xb1, OR_a_r, C)
  op(0xb2, OR_a_r, D)
  op(0xb3, OR_a_r, E)
  op(0xb4, OR_a_r, H)
  op(0xb5, OR_a_r, L)
  op(0xb6, OR_a_irr, HL)
  op(0xb7, OR_a_r, A)
  op(0xb8, CP_a_r, B)
  op(0xb9, CP_a_r, C)
  op(0xba, CP_a_r, D)
  op(0xbb, CP_a_r, E)
  op(0xbc, CP_a_r, H)
  op(0xbd, CP_a_r, L)
  op(0xbe, CP_a_irr, HL)
  op(0xbf, CP_a_r, A)
  op(0xc0, RET_c, ZF == 0)
  op(0xc1, POP_rr, BC)
  op(0xc2, JP_c_nn, ZF == 0)
  op(0xc3, JP_c_nn, 1)
  op(0xc4, CALL_c_nn, ZF == 0)
  op(0xc5, PUSH_rr, BC)
  op(0xc6, ADD_a_n)
  op(0xc7, RST_o, 0)
  op(0xc8, RET_c, ZF == 1)
  op(0xc9, RET)
  op(0xca, JP_c_nn, ZF == 1)
//op(0xcb, cb:)
  op(0xcc, CALL_c_nn, ZF == 1)
  op(0xcd, CALL_nn)
  op(0xce, ADC_a_n)
  op(0xcf, RST_o, 1)
  op(0xd0, RET_c, CF == 0)
  op(0xd1, POP_rr, DE)
  op(0xd2, JP_c_nn, CF == 0)
  op(0xd3, OUT_in_a)
  op(0xd4, CALL_c_nn, CF == 0)
  op(0xd5, PUSH_rr, DE)
  op(0xd6, SUB_a_n)
  op(0xd7, RST_o, 2)
  op(0xd8, RET_c, CF == 1)
  op(0xd9, EXX)
  op(0xda, JP_c_nn, CF == 1)
  op(0xdb, IN_a_in)
  op(0xdc, CALL_c_nn, CF == 1)
//op(0xdd, ix:)
  op(0xde, SBC_a_n)
  op(0xdf, RST_o, 3)
  op(0xe0, RET_c, PF == 0)
  op(0xe1, POP_rr, HL)
  op(0xe2, JP_c_nn, PF == 0)
  op(0xe3, EX_irr_rr, SP, HL)
  op(0xe4, CALL_c_nn, PF == 0)
  op(0xe5, PUSH_rr, HL)
  op(0xe6, AND_a_n)
  op(0xe7, RST_o, 4)
  op(0xe8, RET_c, PF == 1)
  op(0xe9, JP_rr, HL)
  op(0xea, JP_c_nn, PF == 1)
  op(0xeb, EX_rr_rr, DE, _HL)
  op(0xec, CALL_c_nn, PF == 1)
//op(0xed, ed:)
  op(0xee, XOR_a_n)
  op(0xef, RST_o, 5)
  op(0xf0, RET_c, SF == 0)
  op(0xf1, POP_rr, AF)
  op(0xf2, JP_c_nn, SF == 0)
  op(0xf3, DI)
  op(0xf4, CALL_c_nn, SF == 0)
  op(0xf5, PUSH_rr, AF)
  op(0xf6, OR_a_n)
  op(0xf7, RST_o, 6)
  op(0xf8, RET_c, SF == 1)
  op(0xf9, LD_sp_rr, HL)
  op(0xfa, JP_c_nn, SF == 1)
  op(0xfb, EI)
  op(0xfc, CALL_c_nn, SF == 1)
//op(0xfd, iy:)
  op(0xfe, CP_a_n)
  op(0xff, RST_o, 7)
  }
}

auto Z80::instructionCB(uint8 code) -> void {
  switch(code) {
  op(0x00, RLC_r, B)
  op(0x01, RLC_r, C)
  op(0x02, RLC_r, D)
  op(0x03, RLC_r, E)
  op(0x04, RLC_r, H)
  op(0x05, RLC_r, L)
  op(0x06, RLC_irr, _HL)
  op(0x07, RLC_r, A)
  op(0x08, RRC_r, B)
  op(0x09, RRC_r, C)
  op(0x0a, RRC_r, D)
  op(0x0b, RRC_r, E)
  op(0x0c, RRC_r, H)
  op(0x0d, RRC_r, L)
  op(0x0e, RRC_irr, _HL)
  op(0x0f, RRC_r, A)
  op(0x10, RL_r, B)
  op(0x11, RL_r, C)
  op(0x12, RL_r, D)
  op(0x13, RL_r, E)
  op(0x14, RL_r, H)
  op(0x15, RL_r, L)
  op(0x16, RL_irr, _HL)
  op(0x17, RL_r, A)
  op(0x18, RR_r, B)
  op(0x19, RR_r, C)
  op(0x1a, RR_r, D)
  op(0x1b, RR_r, E)
  op(0x1c, RR_r, H)
  op(0x1d, RR_r, L)
  op(0x1e, RR_irr, _HL)
  op(0x1f, RR_r, A)
  op(0x20, SLA_r, B)
  op(0x21, SLA_r, C)
  op(0x22, SLA_r, D)
  op(0x23, SLA_r, E)
  op(0x24, SLA_r, H)
  op(0x25, SLA_r, L)
  op(0x26, SLA_irr, _HL)
  op(0x27, SLA_r, A)
  op(0x28, SRA_r, B)
  op(0x29, SRA_r, C)
  op(0x2a, SRA_r, D)
  op(0x2b, SRA_r, E)
  op(0x2c, SRA_r, H)
  op(0x2d, SRA_r, L)
  op(0x2e, SRA_irr, _HL)
  op(0x2f, SRA_r, A)
  op(0x30, SLL_r, B)
  op(0x31, SLL_r, C)
  op(0x32, SLL_r, D)
  op(0x33, SLL_r, E)
  op(0x34, SLL_r, H)
  op(0x35, SLL_r, L)
  op(0x36, SLL_irr, _HL)
  op(0x37, SLL_r, A)
  op(0x38, SRL_r, B)
  op(0x39, SRL_r, C)
  op(0x3a, SRL_r, D)
  op(0x3b, SRL_r, E)
  op(0x3c, SRL_r, H)
  op(0x3d, SRL_r, L)
  op(0x3e, SRL_irr, _HL)
  op(0x3f, SRL_r, A)
  op(0x40, BIT_o_r, 0, B)
  op(0x41, BIT_o_r, 0, C)
  op(0x42, BIT_o_r, 0, D)
  op(0x43, BIT_o_r, 0, E)
  op(0x44, BIT_o_r, 0, H)
  op(0x45, BIT_o_r, 0, L)
  op(0x46, BIT_o_irr, 0, _HL)
  op(0x47, BIT_o_r, 0, A)
  op(0x48, BIT_o_r, 1, B)
  op(0x49, BIT_o_r, 1, C)
  op(0x4a, BIT_o_r, 1, D)
  op(0x4b, BIT_o_r, 1, E)
  op(0x4c, BIT_o_r, 1, H)
  op(0x4d, BIT_o_r, 1, L)
  op(0x4e, BIT_o_irr, 1, _HL)
  op(0x4f, BIT_o_r, 1, A)
  op(0x50, BIT_o_r, 2, B)
  op(0x51, BIT_o_r, 2, C)
  op(0x52, BIT_o_r, 2, D)
  op(0x53, BIT_o_r, 2, E)
  op(0x54, BIT_o_r, 2, H)
  op(0x55, BIT_o_r, 2, L)
  op(0x56, BIT_o_irr, 2, _HL)
  op(0x57, BIT_o_r, 2, A)
  op(0x58, BIT_o_r, 3, B)
  op(0x59, BIT_o_r, 3, C)
  op(0x5a, BIT_o_r, 3, D)
  op(0x5b, BIT_o_r, 3, E)
  op(0x5c, BIT_o_r, 3, H)
  op(0x5d, BIT_o_r, 3, L)
  op(0x5e, BIT_o_irr, 3, _HL)
  op(0x5f, BIT_o_r, 3, A)
  op(0x60, BIT_o_r, 4, B)
  op(0x61, BIT_o_r, 4, C)
  op(0x62, BIT_o_r, 4, D)
  op(0x63, BIT_o_r, 4, E)
  op(0x64, BIT_o_r, 4, H)
  op(0x65, BIT_o_r, 4, L)
  op(0x66, BIT_o_irr, 4, _HL)
  op(0x67, BIT_o_r, 4, A)
  op(0x68, BIT_o_r, 5, B)
  op(0x69, BIT_o_r, 5, C)
  op(0x6a, BIT_o_r, 5, D)
  op(0x6b, BIT_o_r, 5, E)
  op(0x6c, BIT_o_r, 5, H)
  op(0x6d, BIT_o_r, 5, L)
  op(0x6e, BIT_o_irr, 5, _HL)
  op(0x6f, BIT_o_r, 5, A)
  op(0x70, BIT_o_r, 6, B)
  op(0x71, BIT_o_r, 6, C)
  op(0x72, BIT_o_r, 6, D)
  op(0x73, BIT_o_r, 6, E)
  op(0x74, BIT_o_r, 6, H)
  op(0x75, BIT_o_r, 6, L)
  op(0x76, BIT_o_irr, 6, _HL)
  op(0x77, BIT_o_r, 6, A)
  op(0x78, BIT_o_r, 7, B)
  op(0x79, BIT_o_r, 7, C)
  op(0x7a, BIT_o_r, 7, D)
  op(0x7b, BIT_o_r, 7, E)
  op(0x7c, BIT_o_r, 7, H)
  op(0x7d, BIT_o_r, 7, L)
  op(0x7e, BIT_o_irr, 7, _HL)
  op(0x7f, BIT_o_r, 7, A)
  op(0x80, RES_o_r, 0, B)
  op(0x81, RES_o_r, 0, C)
  op(0x82, RES_o_r, 0, D)
  op(0x83, RES_o_r, 0, E)
  op(0x84, RES_o_r, 0, H)
  op(0x85, RES_o_r, 0, L)
  op(0x86, RES_o_irr, 0, _HL)
  op(0x87, RES_o_r, 0, A)
  op(0x88, RES_o_r, 1, B)
  op(0x89, RES_o_r, 1, C)
  op(0x8a, RES_o_r, 1, D)
  op(0x8b, RES_o_r, 1, E)
  op(0x8c, RES_o_r, 1, H)
  op(0x8d, RES_o_r, 1, L)
  op(0x8e, RES_o_irr, 1, _HL)
  op(0x8f, RES_o_r, 1, A)
  op(0x90, RES_o_r, 2, B)
  op(0x91, RES_o_r, 2, C)
  op(0x92, RES_o_r, 2, D)
  op(0x93, RES_o_r, 2, E)
  op(0x94, RES_o_r, 2, H)
  op(0x95, RES_o_r, 2, L)
  op(0x96, RES_o_irr, 2, _HL)
  op(0x97, RES_o_r, 2, A)
  op(0x98, RES_o_r, 3, B)
  op(0x99, RES_o_r, 3, C)
  op(0x9a, RES_o_r, 3, D)
  op(0x9b, RES_o_r, 3, E)
  op(0x9c, RES_o_r, 3, H)
  op(0x9d, RES_o_r, 3, L)
  op(0x9e, RES_o_irr, 3, _HL)
  op(0x9f, RES_o_r, 3, A)
  op(0xa0, RES_o_r, 4, B)
  op(0xa1, RES_o_r, 4, C)
  op(0xa2, RES_o_r, 4, D)
  op(0xa3, RES_o_r, 4, E)
  op(0xa4, RES_o_r, 4, H)
  op(0xa5, RES_o_r, 4, L)
  op(0xa6, RES_o_irr, 4, _HL)
  op(0xa7, RES_o_r, 4, A)
  op(0xa8, RES_o_r, 5, B)
  op(0xa9, RES_o_r, 5, C)
  op(0xaa, RES_o_r, 5, D)
  op(0xab, RES_o_r, 5, E)
  op(0xac, RES_o_r, 5, H)
  op(0xad, RES_o_r, 5, L)
  op(0xae, RES_o_irr, 5, _HL)
  op(0xaf, RES_o_r, 5, A)
  op(0xb0, RES_o_r, 6, B)
  op(0xb1, RES_o_r, 6, C)
  op(0xb2, RES_o_r, 6, D)
  op(0xb3, RES_o_r, 6, E)
  op(0xb4, RES_o_r, 6, H)
  op(0xb5, RES_o_r, 6, L)
  op(0xb6, RES_o_irr, 6, _HL)
  op(0xb7, RES_o_r, 6, A)
  op(0xb8, RES_o_r, 7, B)
  op(0xb9, RES_o_r, 7, C)
  op(0xba, RES_o_r, 7, D)
  op(0xbb, RES_o_r, 7, E)
  op(0xbc, RES_o_r, 7, H)
  op(0xbd, RES_o_r, 7, L)
  op(0xbe, RES_o_irr, 7, _HL)
  op(0xbf, RES_o_r, 7, A)
  op(0xc0, SET_o_r, 0, B)
  op(0xc1, SET_o_r, 0, C)
  op(0xc2, SET_o_r, 0, D)
  op(0xc3, SET_o_r, 0, E)
  op(0xc4, SET_o_r, 0, H)
  op(0xc5, SET_o_r, 0, L)
  op(0xc6, SET_o_irr, 0, _HL)
  op(0xc7, SET_o_r, 0, A)
  op(0xc8, SET_o_r, 1, B)
  op(0xc9, SET_o_r, 1, C)
  op(0xca, SET_o_r, 1, D)
  op(0xcb, SET_o_r, 1, E)
  op(0xcc, SET_o_r, 1, H)
  op(0xcd, SET_o_r, 1, L)
  op(0xce, SET_o_irr, 1, _HL)
  op(0xcf, SET_o_r, 1, A)
  op(0xd0, SET_o_r, 2, B)
  op(0xd1, SET_o_r, 2, C)
  op(0xd2, SET_o_r, 2, D)
  op(0xd3, SET_o_r, 2, E)
  op(0xd4, SET_o_r, 2, H)
  op(0xd5, SET_o_r, 2, L)
  op(0xd6, SET_o_irr, 2, _HL)
  op(0xd7, SET_o_r, 2, A)
  op(0xd8, SET_o_r, 3, B)
  op(0xd9, SET_o_r, 3, C)
  op(0xda, SET_o_r, 3, D)
  op(0xdb, SET_o_r, 3, E)
  op(0xdc, SET_o_r, 3, H)
  op(0xdd, SET_o_r, 3, L)
  op(0xde, SET_o_irr, 3, _HL)
  op(0xdf, SET_o_r, 3, A)
  op(0xe0, SET_o_r, 4, B)
  op(0xe1, SET_o_r, 4, C)
  op(0xe2, SET_o_r, 4, D)
  op(0xe3, SET_o_r, 4, E)
  op(0xe4, SET_o_r, 4, H)
  op(0xe5, SET_o_r, 4, L)
  op(0xe6, SET_o_irr, 4, _HL)
  op(0xe7, SET_o_r, 4, A)
  op(0xe8, SET_o_r, 5, B)
  op(0xe9, SET_o_r, 5, C)
  op(0xea, SET_o_r, 5, D)
  op(0xeb, SET_o_r, 5, E)
  op(0xec, SET_o_r, 5, H)
  op(0xed, SET_o_r, 5, L)
  op(0xee, SET_o_irr, 5, _HL)
  op(0xef, SET_o_r, 5, A)
  op(0xf0, SET_o_r, 6, B)
  op(0xf1, SET_o_r, 6, C)
  op(0xf2, SET_o_r, 6, D)
  op(0xf3, SET_o_r, 6, E)
  op(0xf4, SET_o_r, 6, H)
  op(0xf5, SET_o_r, 6, L)
  op(0xf6, SET_o_irr, 6, _HL)
  op(0xf7, SET_o_r, 6, A)
  op(0xf8, SET_o_r, 7, B)
  op(0xf9, SET_o_r, 7, C)
  op(0xfa, SET_o_r, 7, D)
  op(0xfb, SET_o_r, 7, E)
  op(0xfc, SET_o_r, 7, H)
  op(0xfd, SET_o_r, 7, L)
  op(0xfe, SET_o_irr, 7, _HL)
  op(0xff, SET_o_r, 7, A)
  }
}

auto Z80::instructionCBd(uint16 addr, uint8 code) -> void {
  uint8 _;

  switch(code) {
  op(0x00, RLC_irr_r, addr, B)
  op(0x01, RLC_irr_r, addr, C)
  op(0x02, RLC_irr_r, addr, D)
  op(0x03, RLC_irr_r, addr, E)
  op(0x04, RLC_irr_r, addr, H)
  op(0x05, RLC_irr_r, addr, L)
  op(0x06, RLC_irr_r, addr, _)
  op(0x07, RLC_irr_r, addr, A)
  op(0x08, RRC_irr_r, addr, B)
  op(0x09, RRC_irr_r, addr, C)
  op(0x0a, RRC_irr_r, addr, D)
  op(0x0b, RRC_irr_r, addr, E)
  op(0x0c, RRC_irr_r, addr, H)
  op(0x0d, RRC_irr_r, addr, L)
  op(0x0e, RRC_irr_r, addr, _)
  op(0x0f, RRC_irr_r, addr, A)
  op(0x10, RL_irr_r, addr, B)
  op(0x11, RL_irr_r, addr, C)
  op(0x12, RL_irr_r, addr, D)
  op(0x13, RL_irr_r, addr, E)
  op(0x14, RL_irr_r, addr, H)
  op(0x15, RL_irr_r, addr, L)
  op(0x16, RL_irr_r, addr, _)
  op(0x17, RL_irr_r, addr, A)
  op(0x18, RR_irr_r, addr, B)
  op(0x19, RR_irr_r, addr, C)
  op(0x1a, RR_irr_r, addr, D)
  op(0x1b, RR_irr_r, addr, E)
  op(0x1c, RR_irr_r, addr, H)
  op(0x1d, RR_irr_r, addr, L)
  op(0x1e, RR_irr_r, addr, _)
  op(0x1f, RR_irr_r, addr, A)
  op(0x20, SLA_irr_r, addr, B)
  op(0x21, SLA_irr_r, addr, C)
  op(0x22, SLA_irr_r, addr, D)
  op(0x23, SLA_irr_r, addr, E)
  op(0x24, SLA_irr_r, addr, H)
  op(0x25, SLA_irr_r, addr, L)
  op(0x26, SLA_irr_r, addr, _)
  op(0x27, SLA_irr_r, addr, A)
  op(0x28, SRA_irr_r, addr, B)
  op(0x29, SRA_irr_r, addr, C)
  op(0x2a, SRA_irr_r, addr, D)
  op(0x2b, SRA_irr_r, addr, E)
  op(0x2c, SRA_irr_r, addr, H)
  op(0x2d, SRA_irr_r, addr, L)
  op(0x2e, SRA_irr_r, addr, _)
  op(0x2f, SRA_irr_r, addr, A)
  op(0x30, SLL_irr_r, addr, B)
  op(0x31, SLL_irr_r, addr, C)
  op(0x32, SLL_irr_r, addr, D)
  op(0x33, SLL_irr_r, addr, E)
  op(0x34, SLL_irr_r, addr, H)
  op(0x35, SLL_irr_r, addr, L)
  op(0x36, SLL_irr_r, addr, _)
  op(0x37, SLL_irr_r, addr, A)
  op(0x38, SRL_irr_r, addr, B)
  op(0x39, SRL_irr_r, addr, C)
  op(0x3a, SRL_irr_r, addr, D)
  op(0x3b, SRL_irr_r, addr, E)
  op(0x3c, SRL_irr_r, addr, H)
  op(0x3d, SRL_irr_r, addr, L)
  op(0x3e, SRL_irr_r, addr, _)
  op(0x3f, SRL_irr_r, addr, A)
  op(0x40, BIT_o_irr_r, 0, addr, B)
  op(0x41, BIT_o_irr_r, 0, addr, C)
  op(0x42, BIT_o_irr_r, 0, addr, D)
  op(0x43, BIT_o_irr_r, 0, addr, E)
  op(0x44, BIT_o_irr_r, 0, addr, H)
  op(0x45, BIT_o_irr_r, 0, addr, L)
  op(0x46, BIT_o_irr_r, 0, addr, _)
  op(0x47, BIT_o_irr_r, 0, addr, A)
  op(0x48, BIT_o_irr_r, 1, addr, B)
  op(0x49, BIT_o_irr_r, 1, addr, C)
  op(0x4a, BIT_o_irr_r, 1, addr, D)
  op(0x4b, BIT_o_irr_r, 1, addr, E)
  op(0x4c, BIT_o_irr_r, 1, addr, H)
  op(0x4d, BIT_o_irr_r, 1, addr, L)
  op(0x4e, BIT_o_irr_r, 1, addr, _)
  op(0x4f, BIT_o_irr_r, 1, addr, A)
  op(0x50, BIT_o_irr_r, 2, addr, B)
  op(0x51, BIT_o_irr_r, 2, addr, C)
  op(0x52, BIT_o_irr_r, 2, addr, D)
  op(0x53, BIT_o_irr_r, 2, addr, E)
  op(0x54, BIT_o_irr_r, 2, addr, H)
  op(0x55, BIT_o_irr_r, 2, addr, L)
  op(0x56, BIT_o_irr_r, 2, addr, _)
  op(0x57, BIT_o_irr_r, 2, addr, A)
  op(0x58, BIT_o_irr_r, 3, addr, B)
  op(0x59, BIT_o_irr_r, 3, addr, C)
  op(0x5a, BIT_o_irr_r, 3, addr, D)
  op(0x5b, BIT_o_irr_r, 3, addr, E)
  op(0x5c, BIT_o_irr_r, 3, addr, H)
  op(0x5d, BIT_o_irr_r, 3, addr, L)
  op(0x5e, BIT_o_irr_r, 3, addr, _)
  op(0x5f, BIT_o_irr_r, 3, addr, A)
  op(0x60, BIT_o_irr_r, 4, addr, B)
  op(0x61, BIT_o_irr_r, 4, addr, C)
  op(0x62, BIT_o_irr_r, 4, addr, D)
  op(0x63, BIT_o_irr_r, 4, addr, E)
  op(0x64, BIT_o_irr_r, 4, addr, H)
  op(0x65, BIT_o_irr_r, 4, addr, L)
  op(0x66, BIT_o_irr_r, 4, addr, _)
  op(0x67, BIT_o_irr_r, 4, addr, A)
  op(0x68, BIT_o_irr_r, 5, addr, B)
  op(0x69, BIT_o_irr_r, 5, addr, C)
  op(0x6a, BIT_o_irr_r, 5, addr, D)
  op(0x6b, BIT_o_irr_r, 5, addr, E)
  op(0x6c, BIT_o_irr_r, 5, addr, H)
  op(0x6d, BIT_o_irr_r, 5, addr, L)
  op(0x6e, BIT_o_irr_r, 5, addr, _)
  op(0x6f, BIT_o_irr_r, 5, addr, A)
  op(0x70, BIT_o_irr_r, 6, addr, B)
  op(0x71, BIT_o_irr_r, 6, addr, C)
  op(0x72, BIT_o_irr_r, 6, addr, D)
  op(0x73, BIT_o_irr_r, 6, addr, E)
  op(0x74, BIT_o_irr_r, 6, addr, H)
  op(0x75, BIT_o_irr_r, 6, addr, L)
  op(0x76, BIT_o_irr_r, 6, addr, _)
  op(0x77, BIT_o_irr_r, 6, addr, A)
  op(0x78, BIT_o_irr_r, 7, addr, B)
  op(0x79, BIT_o_irr_r, 7, addr, C)
  op(0x7a, BIT_o_irr_r, 7, addr, D)
  op(0x7b, BIT_o_irr_r, 7, addr, E)
  op(0x7c, BIT_o_irr_r, 7, addr, H)
  op(0x7d, BIT_o_irr_r, 7, addr, L)
  op(0x7e, BIT_o_irr_r, 7, addr, _)
  op(0x7f, BIT_o_irr_r, 7, addr, A)
  op(0x80, RES_o_irr_r, 0, addr, B)
  op(0x81, RES_o_irr_r, 0, addr, C)
  op(0x82, RES_o_irr_r, 0, addr, D)
  op(0x83, RES_o_irr_r, 0, addr, E)
  op(0x84, RES_o_irr_r, 0, addr, H)
  op(0x85, RES_o_irr_r, 0, addr, L)
  op(0x86, RES_o_irr_r, 0, addr, _)
  op(0x87, RES_o_irr_r, 0, addr, A)
  op(0x88, RES_o_irr_r, 1, addr, B)
  op(0x89, RES_o_irr_r, 1, addr, C)
  op(0x8a, RES_o_irr_r, 1, addr, D)
  op(0x8b, RES_o_irr_r, 1, addr, E)
  op(0x8c, RES_o_irr_r, 1, addr, H)
  op(0x8d, RES_o_irr_r, 1, addr, L)
  op(0x8e, RES_o_irr_r, 1, addr, _)
  op(0x8f, RES_o_irr_r, 1, addr, A)
  op(0x90, RES_o_irr_r, 2, addr, B)
  op(0x91, RES_o_irr_r, 2, addr, C)
  op(0x92, RES_o_irr_r, 2, addr, D)
  op(0x93, RES_o_irr_r, 2, addr, E)
  op(0x94, RES_o_irr_r, 2, addr, H)
  op(0x95, RES_o_irr_r, 2, addr, L)
  op(0x96, RES_o_irr_r, 2, addr, _)
  op(0x97, RES_o_irr_r, 2, addr, A)
  op(0x98, RES_o_irr_r, 3, addr, B)
  op(0x99, RES_o_irr_r, 3, addr, C)
  op(0x9a, RES_o_irr_r, 3, addr, D)
  op(0x9b, RES_o_irr_r, 3, addr, E)
  op(0x9c, RES_o_irr_r, 3, addr, H)
  op(0x9d, RES_o_irr_r, 3, addr, L)
  op(0x9e, RES_o_irr_r, 3, addr, _)
  op(0x9f, RES_o_irr_r, 3, addr, A)
  op(0xa0, RES_o_irr_r, 4, addr, B)
  op(0xa1, RES_o_irr_r, 4, addr, C)
  op(0xa2, RES_o_irr_r, 4, addr, D)
  op(0xa3, RES_o_irr_r, 4, addr, E)
  op(0xa4, RES_o_irr_r, 4, addr, H)
  op(0xa5, RES_o_irr_r, 4, addr, L)
  op(0xa6, RES_o_irr_r, 4, addr, _)
  op(0xa7, RES_o_irr_r, 4, addr, A)
  op(0xa8, RES_o_irr_r, 5, addr, B)
  op(0xa9, RES_o_irr_r, 5, addr, C)
  op(0xaa, RES_o_irr_r, 5, addr, D)
  op(0xab, RES_o_irr_r, 5, addr, E)
  op(0xac, RES_o_irr_r, 5, addr, H)
  op(0xad, RES_o_irr_r, 5, addr, L)
  op(0xae, RES_o_irr_r, 5, addr, _)
  op(0xaf, RES_o_irr_r, 5, addr, A)
  op(0xb0, RES_o_irr_r, 6, addr, B)
  op(0xb1, RES_o_irr_r, 6, addr, C)
  op(0xb2, RES_o_irr_r, 6, addr, D)
  op(0xb3, RES_o_irr_r, 6, addr, E)
  op(0xb4, RES_o_irr_r, 6, addr, H)
  op(0xb5, RES_o_irr_r, 6, addr, L)
  op(0xb6, RES_o_irr_r, 6, addr, _)
  op(0xb7, RES_o_irr_r, 6, addr, A)
  op(0xb8, RES_o_irr_r, 7, addr, B)
  op(0xb9, RES_o_irr_r, 7, addr, C)
  op(0xba, RES_o_irr_r, 7, addr, D)
  op(0xbb, RES_o_irr_r, 7, addr, E)
  op(0xbc, RES_o_irr_r, 7, addr, H)
  op(0xbd, RES_o_irr_r, 7, addr, L)
  op(0xbe, RES_o_irr_r, 7, addr, _)
  op(0xbf, RES_o_irr_r, 7, addr, A)
  op(0xc0, SET_o_irr_r, 0, addr, B)
  op(0xc1, SET_o_irr_r, 0, addr, C)
  op(0xc2, SET_o_irr_r, 0, addr, D)
  op(0xc3, SET_o_irr_r, 0, addr, E)
  op(0xc4, SET_o_irr_r, 0, addr, H)
  op(0xc5, SET_o_irr_r, 0, addr, L)
  op(0xc6, SET_o_irr_r, 0, addr, _)
  op(0xc7, SET_o_irr_r, 0, addr, A)
  op(0xc8, SET_o_irr_r, 1, addr, B)
  op(0xc9, SET_o_irr_r, 1, addr, C)
  op(0xca, SET_o_irr_r, 1, addr, D)
  op(0xcb, SET_o_irr_r, 1, addr, E)
  op(0xcc, SET_o_irr_r, 1, addr, H)
  op(0xcd, SET_o_irr_r, 1, addr, L)
  op(0xce, SET_o_irr_r, 1, addr, _)
  op(0xcf, SET_o_irr_r, 1, addr, A)
  op(0xd0, SET_o_irr_r, 2, addr, B)
  op(0xd1, SET_o_irr_r, 2, addr, C)
  op(0xd2, SET_o_irr_r, 2, addr, D)
  op(0xd3, SET_o_irr_r, 2, addr, E)
  op(0xd4, SET_o_irr_r, 2, addr, H)
  op(0xd5, SET_o_irr_r, 2, addr, L)
  op(0xd6, SET_o_irr_r, 2, addr, _)
  op(0xd7, SET_o_irr_r, 2, addr, A)
  op(0xd8, SET_o_irr_r, 3, addr, B)
  op(0xd9, SET_o_irr_r, 3, addr, C)
  op(0xda, SET_o_irr_r, 3, addr, D)
  op(0xdb, SET_o_irr_r, 3, addr, E)
  op(0xdc, SET_o_irr_r, 3, addr, H)
  op(0xdd, SET_o_irr_r, 3, addr, L)
  op(0xde, SET_o_irr_r, 3, addr, _)
  op(0xdf, SET_o_irr_r, 3, addr, A)
  op(0xe0, SET_o_irr_r, 4, addr, B)
  op(0xe1, SET_o_irr_r, 4, addr, C)
  op(0xe2, SET_o_irr_r, 4, addr, D)
  op(0xe3, SET_o_irr_r, 4, addr, E)
  op(0xe4, SET_o_irr_r, 4, addr, H)
  op(0xe5, SET_o_irr_r, 4, addr, L)
  op(0xe6, SET_o_irr_r, 4, addr, _)
  op(0xe7, SET_o_irr_r, 4, addr, A)
  op(0xe8, SET_o_irr_r, 5, addr, B)
  op(0xe9, SET_o_irr_r, 5, addr, C)
  op(0xea, SET_o_irr_r, 5, addr, D)
  op(0xeb, SET_o_irr_r, 5, addr, E)
  op(0xec, SET_o_irr_r, 5, addr, H)
  op(0xed, SET_o_irr_r, 5, addr, L)
  op(0xee, SET_o_irr_r, 5, addr, _)
  op(0xef, SET_o_irr_r, 5, addr, A)
  op(0xf0, SET_o_irr_r, 6, addr, B)
  op(0xf1, SET_o_irr_r, 6, addr, C)
  op(0xf2, SET_o_irr_r, 6, addr, D)
  op(0xf3, SET_o_irr_r, 6, addr, E)
  op(0xf4, SET_o_irr_r, 6, addr, H)
  op(0xf5, SET_o_irr_r, 6, addr, L)
  op(0xf6, SET_o_irr_r, 6, addr, _)
  op(0xf7, SET_o_irr_r, 6, addr, A)
  op(0xf8, SET_o_irr_r, 7, addr, B)
  op(0xf9, SET_o_irr_r, 7, addr, C)
  op(0xfa, SET_o_irr_r, 7, addr, D)
  op(0xfb, SET_o_irr_r, 7, addr, E)
  op(0xfc, SET_o_irr_r, 7, addr, H)
  op(0xfd, SET_o_irr_r, 7, addr, L)
  op(0xfe, SET_o_irr_r, 7, addr, _)
  op(0xff, SET_o_irr_r, 7, addr, A)
  }
}

auto Z80::instructionED(uint8 code) -> void {
  switch(code) {
  op(0x40, IN_r_ic, B)
  op(0x41, OUT_ic_r, B)
  op(0x42, SBC_hl_rr, BC)
  op(0x43, LD_inn_rr, BC)
  op(0x44, NEG)
  op(0x45, RETN)
  op(0x46, IM_o, 0)
  op(0x47, LD_r_r1, I, A)
  op(0x48, IN_r_ic, C)
  op(0x49, OUT_ic_r, C)
  op(0x4a, ADC_hl_rr, BC)
  op(0x4b, LD_rr_inn, BC)
  op(0x4c, NEG)
  op(0x4d, RETI)
  op(0x4e, IM_o, 0)
  op(0x4f, LD_r_r1, R, A)
  op(0x50, IN_r_ic, D)
  op(0x51, OUT_ic_r, D)
  op(0x52, SBC_hl_rr, DE)
  op(0x53, LD_inn_rr, DE)
  op(0x54, NEG)
  op(0x55, RETN)
  op(0x56, IM_o, 1)
  op(0x57, LD_r_r2, A, I)
  op(0x58, IN_r_ic, E)
  op(0x59, OUT_ic_r, E)
  op(0x5a, ADC_hl_rr, DE)
  op(0x5b, LD_rr_inn, DE)
  op(0x5c, NEG)
  op(0x5d, RETI)
  op(0x5e, IM_o, 2)
  op(0x5f, LD_r_r2, A, R)
  op(0x60, IN_r_ic, H)
  op(0x61, OUT_ic_r, H)
  op(0x62, SBC_hl_rr, HL)
  op(0x63, LD_inn_rr, HL)
  op(0x64, NEG)
  op(0x65, RETN)
  op(0x66, IM_o, 0)
  op(0x67, RRD)
  op(0x68, IN_r_ic, L)
  op(0x69, OUT_ic_r, L)
  op(0x6a, ADC_hl_rr, HL)
  op(0x6b, LD_rr_inn, HL)
  op(0x6c, NEG)
  op(0x6d, RETI)
  op(0x6e, IM_o, 0)
  op(0x6f, RLD)
  op(0x70, IN_ic)
  op(0x71, OUT_ic)
  op(0x72, SBC_hl_rr, SP)
  op(0x73, LD_inn_rr, SP)
  op(0x74, NEG)
  op(0x75, RETN)
  op(0x76, IM_o, 1)
  op(0x77, NOP)
  op(0x78, IN_r_ic, A)
  op(0x79, OUT_ic_r, A)
  op(0x7a, ADC_hl_rr, SP)
  op(0x7b, LD_rr_inn, SP)
  op(0x7c, NEG)
  op(0x7d, RETI)
  op(0x7e, IM_o, 2)
  op(0x7f, NOP)
  op(0xa0, LDI)
  op(0xa1, CPI)
  op(0xa2, INI)
  op(0xa3, OUTI)
  op(0xa8, LDD)
  op(0xa9, CPD)
  op(0xaa, IND)
  op(0xab, OUTD)
  op(0xb0, LDIR)
  op(0xb1, CPIR)
  op(0xb2, INIR)
  op(0xb3, OTIR)
  op(0xb8, LDDR)
  op(0xb9, CPDR)
  op(0xba, INDR)
  op(0xbb, OTDR)
  }

  //undefined instructions are NOP
  return instructionNOP();
}

#undef op
