auto Z80::disassemble(uint16 pc) -> string { string s; s.append(hex(pc, 4L), " "); uint8 prefix = 0x00; auto code = bus->read(pc++); if(code == 0xdd || code == 0xfd) { prefix = code; code = bus->read(pc++); if(code == 0xdd || code == 0xfd) { if(prefix == 0xdd) { s.append("ix:"); goto finish; } if(prefix == 0xfd) { s.append("iy:"); goto finish; } } } s.append(pad(disassemble__(pc, prefix, code), -18L, ' ')); finish: s.append(" AF:", hex(r.af.word, 4L)); s.append(" BC:", hex(r.bc.word, 4L)); s.append(" DE:", hex(r.de.word, 4L)); s.append(" HL:", hex(r.hl.word, 4L)); s.append(" IX:", hex(r.ix.word, 4L)); s.append(" IY:", hex(r.iy.word, 4L)); s.append(" SP:", hex(r.sp, 4L)); return s; } #define op(id, name, ...) case id: return {name, " ", string_vector{__VA_ARGS__}.merge(",")}; #define N string{"$", hex(byte(), 2L)} #define IN string{"(", N, ")"} #define NN string{"$", hex(word(), 4L)} #define INN string{"(", NN, ")"} #define R string{"$", hex(branch(), 4L)} #define A "a" #define F "f" #define B "b" #define C "c" #define D "d" #define E "e" #define H prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h" #define L prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l" #define _H "h" #define _L "l" #define _HL "hl" #define AF "af" #define BC "bc" #define DE "de" #define HL prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl" #define AF_ "af'" #define BC_ "bc'" #define DE_ "de'" #define HL_ "hl'" #define SP "sp" #define PC "pc" #define IBC "(bc)" #define IDE "(de)" #define IHL string{"(", HL, displace(), ")"} #define ISP "(sp)" auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { auto byte = [&] { return bus->read(pc++); }; auto word = [&] { uint16 data = byte() << 0; return data | byte() << 8; }; auto branch = [&] { auto d = byte(); return pc + (int8)d; }; auto displace = [&] { if(!prefix) return string{}; auto d = (int8)byte(); return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; }; if(code == 0xcb) return code = byte(), disassembleCB(pc, prefix, code); if(code == 0xed) return code = byte(), disassembleED(pc, prefix, code); switch(code) { op(0x00, "nop ") op(0x01, "ld ", BC, NN) op(0x02, "ld ", IBC, A) op(0x03, "inc ", BC) op(0x04, "inc ", B) op(0x05, "dec ", B) op(0x06, "ld ", B, N) op(0x07, "rlca") op(0x08, "ex ", AF, AF_) op(0x09, "add ", HL, BC) op(0x0a, "ld ", A, IBC) op(0x0b, "dec ", BC) op(0x0c, "inc ", C) op(0x0d, "dec ", C) op(0x0e, "ld ", C, N) op(0x0f, "rrca") op(0x11, "ld ", DE, NN) op(0x12, "ld ", IDE, A) op(0x13, "inc ", DE) op(0x14, "inc ", D) op(0x15, "dec ", D) op(0x16, "ld ", E, N) op(0x17, "rla ") op(0x18, "jr ", R) op(0x19, "add ", HL, DE) op(0x1a, "ld ", A, IDE) op(0x1b, "dec ", DE) op(0x1c, "inc ", E) op(0x1d, "dec ", E) op(0x1e, "ld ", E, N) op(0x1f, "rra ") op(0x20, "jr ", "nz", R) op(0x21, "ld ", HL, NN) op(0x22, "ld ", INN, HL) op(0x23, "inc ", HL) op(0x24, "inc ", H) op(0x25, "dec ", H) op(0x26, "ld ", H, N) op(0x28, "jr ", "z", R) op(0x29, "add ", HL, HL) op(0x2a, "ld ", HL, INN) op(0x2b, "dec ", HL) op(0x2c, "inc ", L) op(0x2d, "dec ", L) op(0x2e, "ld ", L, N) op(0x2f, "cpl ") op(0x30, "jr ", "nc", R) op(0x31, "ld ", SP, NN) op(0x32, "ld ", INN, A) op(0x33, "inc ", SP) op(0x34, "inc ", IHL) op(0x35, "dec ", IHL) op(0x36, "ld ", IHL, N) op(0x37, "scf ") op(0x38, "jr ", "c", R) op(0x39, "add ", HL, SP) op(0x3a, "ld ", A, INN) op(0x3b, "dec ", SP) op(0x3c, "inc ", A) op(0x3d, "dec ", A) op(0x3e, "ld ", A, N) op(0x3f, "ccf ") op(0x40, "ld ", B, B) op(0x41, "ld ", B, C) op(0x42, "ld ", B, D) op(0x43, "ld ", B, E) op(0x44, "ld ", B, H) op(0x45, "ld ", B, L) op(0x46, "ld ", B, IHL) op(0x47, "ld ", B, A) op(0x48, "ld ", C, B) op(0x49, "ld ", C, C) op(0x4a, "ld ", C, D) op(0x4b, "ld ", C, E) op(0x4c, "ld ", C, H) op(0x4d, "ld ", C, L) op(0x4e, "ld ", C, IHL) op(0x4f, "ld ", C, A) op(0x50, "ld ", D, B) op(0x51, "ld ", D, C) op(0x52, "ld ", D, D) op(0x53, "ld ", D, E) op(0x54, "ld ", D, H) op(0x55, "ld ", D, L) op(0x56, "ld ", D, IHL) op(0x57, "ld ", D, A) op(0x58, "ld ", E, B) op(0x59, "ld ", E, C) op(0x5a, "ld ", E, D) op(0x5b, "ld ", E, E) op(0x5c, "ld ", E, H) op(0x5d, "ld ", E, L) op(0x5e, "ld ", E, IHL) op(0x5f, "ld ", E, A) op(0x60, "ld ", H, B) op(0x61, "ld ", H, C) op(0x62, "ld ", H, D) op(0x63, "ld ", H, E) op(0x64, "ld ", H, H) op(0x65, "ld ", H, L) op(0x66, "ld ", _H, IHL) op(0x67, "ld ", H, A) op(0x68, "ld ", L, B) op(0x69, "ld ", L, C) op(0x6a, "ld ", L, D) op(0x6b, "ld ", L, E) op(0x6c, "ld ", L, H) op(0x6d, "ld ", L, L) op(0x6e, "ld ", _L, IHL) op(0x6f, "ld ", L, A) op(0x70, "ld ", IHL, B) op(0x71, "ld ", IHL, C) op(0x72, "ld ", IHL, D) op(0x73, "ld ", IHL, E) op(0x74, "ld ", IHL, _H) op(0x75, "ld ", IHL, _L) op(0x76, "halt") op(0x77, "ld ", IHL, A) op(0x78, "ld ", A, B) op(0x79, "ld ", A, C) op(0x7a, "ld ", A, D) op(0x7b, "ld ", A, E) op(0x7c, "ld ", A, H) op(0x7d, "ld ", A, L) op(0x7e, "ld ", A, IHL) op(0x7f, "ld ", A, A) op(0x80, "add ", A, B) op(0x81, "add ", A, C) op(0x82, "add ", A, D) op(0x83, "add ", A, E) op(0x84, "add ", A, H) op(0x85, "add ", A, L) op(0x86, "add ", A, IHL) op(0x87, "add ", A, A) op(0x88, "adc ", A, B) op(0x89, "adc ", A, C) op(0x8a, "adc ", A, D) op(0x8b, "adc ", A, E) op(0x8c, "adc ", A, H) op(0x8d, "adc ", A, L) op(0x8e, "adc ", A, IHL) op(0x8f, "adc ", A, A) op(0x90, "sub ", A, B) op(0x91, "sub ", A, C) op(0x92, "sub ", A, D) op(0x93, "sub ", A, E) op(0x94, "sub ", A, H) op(0x95, "sub ", A, L) op(0x96, "sub ", A, IHL) op(0x97, "sub ", A, A) op(0x98, "sbc ", A, B) op(0x99, "sbc ", A, C) op(0x9a, "sbc ", A, D) op(0x9b, "sbc ", A, E) op(0x9c, "sbc ", A, H) op(0x9d, "sbc ", A, L) op(0x9e, "sbc ", A, IHL) op(0x9f, "sbc ", A, A) op(0xa0, "and ", A, B) op(0xa1, "and ", A, C) op(0xa2, "and ", A, D) op(0xa3, "and ", A, E) op(0xa4, "and ", A, H) op(0xa5, "and ", A, L) op(0xa6, "and ", A, IHL) op(0xa7, "and ", A, A) op(0xa8, "xor ", A, B) op(0xa9, "xor ", A, C) op(0xaa, "xor ", A, D) op(0xab, "xor ", A, E) op(0xac, "xor ", A, H) op(0xad, "xor ", A, L) op(0xae, "xor ", A, HL) op(0xaf, "xor ", A, A) op(0xb0, "or ", A, B) op(0xb1, "or ", A, C) op(0xb2, "or ", A, D) op(0xb3, "or ", A, E) op(0xb4, "or ", A, H) op(0xb5, "or ", A, L) op(0xb6, "or ", A, IHL) op(0xb7, "or ", A, A) op(0xb8, "cp ", A, B) op(0xb9, "cp ", A, C) op(0xba, "cp ", A, D) op(0xbb, "cp ", A, E) op(0xbc, "cp ", A, H) op(0xbd, "cp ", A, L) op(0xbe, "cp ", A, IHL) op(0xbf, "cp ", A, A) op(0xc2, "jp ", "nz", NN) op(0xc3, "jp ", NN) op(0xca, "jp ", "z", NN) op(0xcb, "cb: ") op(0xd2, "jp ", "nc", NN) op(0xda, "jp ", "c", NN) op(0xdb, "in ", A, IN) op(0xe2, "jp ", "po", NN) op(0xea, "jp ", "pe", NN) op(0xeb, "ex ", DE, _HL) op(0xed, "ed: ") op(0xf2, "jp ", "p", NN) op(0xf3, "di ") op(0xfa, "jp ", "m", NN) op(0xfb, "ei ") op(0xfe, "cp ", A, N) } return {"???: ", hex(code, 2L)}; } auto Z80::disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string { auto byte = [&] { return bus->read(pc++); }; auto word = [&] { uint16 data = byte() << 0; return data | byte() << 8; }; auto branch = [&] { auto d = byte(); return pc + (int8)d; }; auto displace = [&] { if(!prefix) return string{}; auto d = (int8)byte(); return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; }; switch(code) { op(0x00, "rlc ", B) op(0x01, "rlc ", C) op(0x02, "rlc ", D) op(0x03, "rlc ", E) op(0x04, "rlc ", H) op(0x05, "rlc ", L) op(0x06, "rlc ", IHL) op(0x07, "rlc ", A) op(0x08, "rrc ", B) op(0x09, "rrc ", C) op(0x0a, "rrc ", D) op(0x0b, "rrc ", E) op(0x0c, "rrc ", H) op(0x0d, "rrc ", L) op(0x0e, "rrc ", IHL) op(0x0f, "rrc ", A) op(0x10, "rl ", B) op(0x11, "rl ", C) op(0x12, "rl ", D) op(0x13, "rl ", E) op(0x14, "rl ", H) op(0x15, "rl ", L) op(0x16, "rl ", IHL) op(0x17, "rl ", A) op(0x18, "rr ", B) op(0x19, "rr ", C) op(0x1a, "rr ", D) op(0x1b, "rr ", E) op(0x1c, "rr ", H) op(0x1d, "rr ", L) op(0x1e, "rr ", IHL) op(0x1f, "rr ", A) op(0x20, "sla ", B) op(0x21, "sla ", C) op(0x22, "sla ", D) op(0x23, "sla ", E) op(0x24, "sla ", H) op(0x25, "sla ", L) op(0x26, "sla ", IHL) op(0x27, "sla ", A) op(0x28, "sra ", B) op(0x29, "sra ", C) op(0x2a, "sra ", D) op(0x2b, "sra ", E) op(0x2c, "sra ", H) op(0x2d, "sra ", L) op(0x2e, "sra ", IHL) op(0x2f, "sra ", A) op(0x30, "sll ", B) op(0x31, "sll ", C) op(0x32, "sll ", D) op(0x33, "sll ", E) op(0x34, "sll ", H) op(0x35, "sll ", L) op(0x36, "sll ", IHL) op(0x37, "sll ", A) op(0x38, "srl ", B) op(0x39, "srl ", C) op(0x3a, "srl ", D) op(0x3b, "srl ", E) op(0x3c, "srl ", H) op(0x3d, "srl ", L) op(0x3e, "srl ", IHL) op(0x3f, "srl ", A) op(0x40, "bit ", "0,", B) op(0x41, "bit ", "0,", C) op(0x42, "bit ", "0,", D) op(0x43, "bit ", "0,", E) op(0x44, "bit ", "0,", H) op(0x45, "bit ", "0,", L) op(0x46, "bit ", "0,", IHL) op(0x47, "bit ", "0,", A) op(0x48, "bit ", "1,", B) op(0x49, "bit ", "1,", C) op(0x4a, "bit ", "1,", D) op(0x4b, "bit ", "1,", E) op(0x4c, "bit ", "1,", H) op(0x4d, "bit ", "1,", L) op(0x4e, "bit ", "1,", IHL) op(0x4f, "bit ", "1,", A) op(0x50, "bit ", "2,", B) op(0x51, "bit ", "2,", C) op(0x52, "bit ", "2,", D) op(0x53, "bit ", "2,", E) op(0x54, "bit ", "2,", H) op(0x55, "bit ", "2,", L) op(0x56, "bit ", "2,", IHL) op(0x57, "bit ", "2,", A) op(0x58, "bit ", "3,", B) op(0x59, "bit ", "3,", C) op(0x5a, "bit ", "3,", D) op(0x5b, "bit ", "3,", E) op(0x5c, "bit ", "3,", H) op(0x5d, "bit ", "3,", L) op(0x5e, "bit ", "3,", IHL) op(0x5f, "bit ", "3,", A) op(0x60, "bit ", "4,", B) op(0x61, "bit ", "4,", C) op(0x62, "bit ", "4,", D) op(0x63, "bit ", "4,", E) op(0x64, "bit ", "4,", H) op(0x65, "bit ", "4,", L) op(0x66, "bit ", "4,", IHL) op(0x67, "bit ", "4,", A) op(0x68, "bit ", "5,", B) op(0x69, "bit ", "5,", C) op(0x6a, "bit ", "5,", D) op(0x6b, "bit ", "5,", E) op(0x6c, "bit ", "5,", H) op(0x6d, "bit ", "5,", L) op(0x6e, "bit ", "5,", IHL) op(0x6f, "bit ", "5,", A) op(0x70, "bit ", "6,", B) op(0x71, "bit ", "6,", C) op(0x72, "bit ", "6,", D) op(0x73, "bit ", "6,", E) op(0x74, "bit ", "6,", H) op(0x75, "bit ", "6,", L) op(0x76, "bit ", "6,", IHL) op(0x77, "bit ", "6,", A) op(0x78, "bit ", "7,", B) op(0x79, "bit ", "7,", C) op(0x7a, "bit ", "7,", D) op(0x7b, "bit ", "7,", E) op(0x7c, "bit ", "7,", H) op(0x7d, "bit ", "7,", L) op(0x7e, "bit ", "7,", IHL) op(0x7f, "bit ", "7,", A) op(0x80, "res ", "0,", B) op(0x81, "res ", "0,", C) op(0x82, "res ", "0,", D) op(0x83, "res ", "0,", E) op(0x84, "res ", "0,", H) op(0x85, "res ", "0,", L) op(0x86, "res ", "0,", IHL) op(0x87, "res ", "0,", A) op(0x88, "res ", "1,", B) op(0x89, "res ", "1,", C) op(0x8a, "res ", "1,", D) op(0x8b, "res ", "1,", E) op(0x8c, "res ", "1,", H) op(0x8d, "res ", "1,", L) op(0x8e, "res ", "1,", IHL) op(0x8f, "res ", "1,", A) op(0x90, "res ", "2,", B) op(0x91, "res ", "2,", C) op(0x92, "res ", "2,", D) op(0x93, "res ", "2,", E) op(0x94, "res ", "2,", H) op(0x95, "res ", "2,", L) op(0x96, "res ", "2,", IHL) op(0x97, "res ", "2,", A) op(0x98, "res ", "3,", B) op(0x99, "res ", "3,", C) op(0x9a, "res ", "3,", D) op(0x9b, "res ", "3,", E) op(0x9c, "res ", "3,", H) op(0x9d, "res ", "3,", L) op(0x9e, "res ", "3,", IHL) op(0x9f, "res ", "3,", A) op(0xa0, "res ", "4,", B) op(0xa1, "res ", "4,", C) op(0xa2, "res ", "4,", D) op(0xa3, "res ", "4,", E) op(0xa4, "res ", "4,", H) op(0xa5, "res ", "4,", L) op(0xa6, "res ", "4,", IHL) op(0xa7, "res ", "4,", A) op(0xa8, "res ", "5,", B) op(0xa9, "res ", "5,", C) op(0xaa, "res ", "5,", D) op(0xab, "res ", "5,", E) op(0xac, "res ", "5,", H) op(0xad, "res ", "5,", L) op(0xae, "res ", "5,", IHL) op(0xaf, "res ", "5,", A) op(0xb0, "res ", "6,", B) op(0xb1, "res ", "6,", C) op(0xb2, "res ", "6,", D) op(0xb3, "res ", "6,", E) op(0xb4, "res ", "6,", H) op(0xb5, "res ", "6,", L) op(0xb6, "res ", "6,", IHL) op(0xb7, "res ", "6,", A) op(0xb8, "res ", "7,", B) op(0xb9, "res ", "7,", C) op(0xba, "res ", "7,", D) op(0xbb, "res ", "7,", E) op(0xbc, "res ", "7,", H) op(0xbd, "res ", "7,", L) op(0xbe, "res ", "7,", IHL) op(0xbf, "res ", "7,", A) op(0xc0, "set ", "0,", B) op(0xc1, "set ", "0,", C) op(0xc2, "set ", "0,", D) op(0xc3, "set ", "0,", E) op(0xc4, "set ", "0,", H) op(0xc5, "set ", "0,", L) op(0xc6, "set ", "0,", IHL) op(0xc7, "set ", "0,", A) op(0xc8, "set ", "1,", B) op(0xc9, "set ", "1,", C) op(0xca, "set ", "1,", D) op(0xcb, "set ", "1,", E) op(0xcc, "set ", "1,", H) op(0xcd, "set ", "1,", L) op(0xce, "set ", "1,", IHL) op(0xcf, "set ", "1,", A) op(0xd0, "set ", "2,", B) op(0xd1, "set ", "2,", C) op(0xd2, "set ", "2,", D) op(0xd3, "set ", "2,", E) op(0xd4, "set ", "2,", H) op(0xd5, "set ", "2,", L) op(0xd6, "set ", "2,", IHL) op(0xd7, "set ", "2,", A) op(0xd8, "set ", "3,", B) op(0xd9, "set ", "3,", C) op(0xda, "set ", "3,", D) op(0xdb, "set ", "3,", E) op(0xdc, "set ", "3,", H) op(0xdd, "set ", "3,", L) op(0xde, "set ", "3,", IHL) op(0xdf, "set ", "3,", A) op(0xe0, "set ", "4,", B) op(0xe1, "set ", "4,", C) op(0xe2, "set ", "4,", D) op(0xe3, "set ", "4,", E) op(0xe4, "set ", "4,", H) op(0xe5, "set ", "4,", L) op(0xe6, "set ", "4,", IHL) op(0xe7, "set ", "4,", A) op(0xe8, "set ", "5,", B) op(0xe9, "set ", "5,", C) op(0xea, "set ", "5,", D) op(0xeb, "set ", "5,", E) op(0xec, "set ", "5,", H) op(0xed, "set ", "5,", L) op(0xee, "set ", "5,", IHL) op(0xef, "set ", "5,", A) op(0xf0, "set ", "6,", B) op(0xf1, "set ", "6,", C) op(0xf2, "set ", "6,", D) op(0xf3, "set ", "6,", E) op(0xf4, "set ", "6,", H) op(0xf5, "set ", "6,", L) op(0xf6, "set ", "6,", IHL) op(0xf7, "set ", "6,", A) op(0xf8, "set ", "7,", B) op(0xf9, "set ", "7,", C) op(0xfa, "set ", "7,", D) op(0xfb, "set ", "7,", E) op(0xfc, "set ", "7,", H) op(0xfd, "set ", "7,", L) op(0xfe, "set ", "7,", IHL) op(0xff, "set ", "7,", A) } unreachable; } auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string { auto byte = [&] { return bus->read(pc++); }; auto word = [&] { uint16 data = byte() << 0; return data | byte() << 8; }; auto branch = [&] { auto d = byte(); return pc + (int8)d; }; auto displace = [&] { if(!prefix) return string{}; auto d = (int8)byte(); return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; }; switch(code) { op(0x46, "im ", "0") op(0x56, "im ", "1") op(0x5e, "im ", "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") } return {"???: ed ", hex(code, 2L)}; } #undef op #undef N #undef IN #undef NN #undef INN #undef R #undef A #undef F #undef B #undef C #undef D #undef E #undef H #undef L #undef _H #undef _L #undef _HL #undef AF #undef BC #undef DE #undef HL #undef AF_ #undef BC_ #undef DE_ #undef HL_ #undef SP #undef PC #undef IBC #undef IDE #undef IHL #undef ISP