auto Z80::trap(uint8 prefix, uint8 code) -> void { print("[Z80] unimplemented instruction: ", prefix ? pad(hex(prefix, 2L), -3L, ' ') : "", hex(code, 2L), "\n"); print("[Z80] instructions executed: ", --instructionsExecuted, "\n"); while(true) wait(); } auto Z80::instruction() -> void { #if 1 if(instructionsExecuted < 20) print(disassemble(r.pc), "\n"); #endif instructionsExecuted++; auto code = opcode(); if(code == 0xdd) { r.hlp = &r.ix; return; } if(code == 0xfd) { r.hlp = &r.iy; return; } instruction__(code); r.hlp = &r.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_rr_rr, HL, 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_rr_rr, HL, 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_rr_rr, HL, 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_rr_rr, HL, 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, opcode()) 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_n_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(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, opcode()) 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::instructionED(uint8 code) -> void { switch(code) { op(0x40, IN_r_ic, B) op(0x41, OUT_ic_r, B) op(0x44, NEG) op(0x45, RETN) op(0x46, IM_o, 0) op(0x48, IN_r_ic, C) op(0x49, OUT_ic_r, C) op(0x4c, NEG) op(0x4d, RETI) op(0x4e, IM_o, 0) op(0x50, IN_r_ic, D) op(0x51, OUT_ic_r, D) op(0x54, NEG) op(0x55, RETN) op(0x56, IM_o, 1) op(0x58, IN_r_ic, E) op(0x59, OUT_ic_r, E) op(0x5c, NEG) op(0x5d, RETI) op(0x5e, IM_o, 2) op(0x60, IN_r_ic, H) op(0x61, OUT_ic_r, H) op(0x64, NEG) op(0x65, RETN) op(0x66, IM_o, 0) op(0x68, IN_r_ic, L) op(0x69, OUT_ic_r, L) op(0x6c, NEG) op(0x6d, RETI) op(0x6e, IM_o, 0) op(0x70, IN_r_ic, F) op(0x71, OUT_ic_r, F) op(0x74, NEG) op(0x75, RETN) op(0x76, IM_o, 1) op(0x78, IN_r_ic, A) op(0x79, OUT_ic_r, A) op(0x7c, NEG) op(0x7d, RETI) op(0x7e, IM_o, 2) 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) } trap(0xed, code); } #undef op