From d6e9d94ec3ee4aefc7fd5d907eed97214077b2e3 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 6 Sep 2016 23:53:14 +1000 Subject: [PATCH] Update to v101r17 release. byuu says: Changelog: - Z80: added most opcodes between 0x00 and 0x3f (two or three hard ones missing still) - Z80: redid register declaration *again* to handle AF', BC', DE', HL' (ugggggh, the fuck? Alternate registers??) - basically, using `#define ` values to get around horrendously awful naming syntax - Z80: improved handling of displace() so that it won't ever trigger on (BC) or (DE) --- higan/emulator/emulator.hpp | 2 +- higan/processor/z80/disassembler.cpp | 98 ++++++++-- higan/processor/z80/instruction.cpp | 114 +++++------ higan/processor/z80/instructions.cpp | 282 +++++++++++++++++++++------ higan/processor/z80/memory.cpp | 2 +- higan/processor/z80/registers.cpp | 51 +++++ higan/processor/z80/z80.cpp | 20 +- higan/processor/z80/z80.hpp | 84 ++++---- 8 files changed, 448 insertions(+), 205 deletions(-) create mode 100644 higan/processor/z80/registers.cpp diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index ba76d0ab..3f4a05c8 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "101.16"; + static const string Version = "101.17"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/z80/disassembler.cpp b/higan/processor/z80/disassembler.cpp index b76be29e..d17281df 100644 --- a/higan/processor/z80/disassembler.cpp +++ b/higan/processor/z80/disassembler.cpp @@ -23,12 +23,12 @@ auto Z80::disassemble(uint16 pc) -> string { s.append(pad(disassemble__(pc, prefix, code), -18L, ' ')); finish: - s.append(" AF:", hex(r.af, 4L)); - s.append(" BC:", hex(r.bc, 4L)); - s.append(" DE:", hex(r.de, 4L)); - s.append(" HL:", hex(r.hl, 4L)); - s.append(" IX:", hex(r.ix, 4L)); - s.append(" IY:", hex(r.iy, 4L)); + 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; @@ -50,16 +50,27 @@ auto Z80::disassemble(uint16 pc) -> string { #define E "e" #define H prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h" #define L prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l" -#define HD "h" -#define LD "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 SP "sp" +#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 = [&] { @@ -88,23 +99,66 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { 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) @@ -143,7 +197,7 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { op(0x63, "ld ", H, E) op(0x64, "ld ", H, H) op(0x65, "ld ", H, L) - op(0x66, "ld ", HD, IHL) + op(0x66, "ld ", _H, IHL) op(0x67, "ld ", H, A) op(0x68, "ld ", L, B) op(0x69, "ld ", L, C) @@ -151,14 +205,14 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { op(0x6b, "ld ", L, E) op(0x6c, "ld ", L, H) op(0x6d, "ld ", L, L) - op(0x6e, "ld ", LD, IHL) + 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, HD) - op(0x75, "ld ", IHL, LD) + op(0x74, "ld ", IHL, _H) + op(0x75, "ld ", IHL, _L) op(0x76, "halt") op(0x77, "ld ", IHL, A) op(0x78, "ld ", A, B) @@ -242,6 +296,7 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { 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 ") @@ -290,13 +345,24 @@ auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string { #undef E #undef H #undef L -#undef HD -#undef LD +#undef _H +#undef _L +#undef _HL #undef AF #undef BC #undef DE #undef HL -#undef SP +#undef AF_ +#undef BC_ +#undef DE_ +#undef HL_ + +#undef SP +#undef PC + +#undef IBC +#undef IDE #undef IHL +#undef ISP diff --git a/higan/processor/z80/instruction.cpp b/higan/processor/z80/instruction.cpp index 7ad9d23a..4c3b7231 100644 --- a/higan/processor/z80/instruction.cpp +++ b/higan/processor/z80/instruction.cpp @@ -13,64 +13,78 @@ auto Z80::instruction() -> void { instructionsExecuted++; auto code = opcode(); - if(code == 0xdd || code == 0xfd) { - r.prefix = code; - return; - } + if(code == 0xdd) { r.hlp = &r.ix; return; } + if(code == 0xfd) { r.hlp = &r.iy; return; } instruction__(code); - r.prefix = 0x00; + r.hlp = &r.hl; } #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); -#define A (uint8&)(r.a) -#define F (uint8&)(r.f) -#define B (uint8&)(r.b) -#define C (uint8&)(r.c) -#define D (uint8&)(r.d) -#define E (uint8&)(r.e) -#define H (uint8&)(r.prefix == 0xdd ? r.ixh : r.prefix == 0xfd ? r.iyh : r.h) -#define L (uint8&)(r.prefix == 0xdd ? r.ixl : r.prefix == 0xfd ? r.iyl : r.l) -#define HD (uint8&)(r.h) -#define LD (uint8&)(r.l) - -#define AF (uint16&)(r.af) -#define BC (uint16&)(r.bc) -#define DE (uint16&)(r.de) -#define HL (uint16&)(r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl) -#define SP (uint16&)(r.sp) - -#define CF r.p.c -#define NF r.p.n -#define PF r.p.p -#define VF r.p.v -#define XF r.p.x -#define HF r.p.h -#define YF r.p.y -#define ZF r.p.z -#define SF r.p.s - 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(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(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) @@ -109,7 +123,7 @@ auto Z80::instruction__(uint8 code) -> void { 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, HD, HL) + 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) @@ -117,14 +131,14 @@ auto Z80::instruction__(uint8 code) -> void { 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, LD, HL) + 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, HD) - op(0x75, LD_irr_r, HL, LD) + 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) @@ -208,6 +222,7 @@ auto Z80::instruction__(uint8 code) -> void { op(0xdb, IN_a_in) op(0xe2, JP_c_nn, PF == 0) op(0xea, JP_c_nn, PF == 1) + op(0xeb, EX_rr_rr, DE, _HL) op(0xed, ED, opcode()) op(0xf2, JP_c_nn, SF == 0) op(0xf3, DI) @@ -237,30 +252,3 @@ auto Z80::instructionED(uint8 code) -> void { } #undef op - -#undef A -#undef F -#undef B -#undef C -#undef D -#undef E -#undef H -#undef L -#undef HD -#undef LD - -#undef AF -#undef BC -#undef DE -#undef HL -#undef SP - -#undef CF -#undef NF -#undef PF -#undef VF -#undef XF -#undef HF -#undef YF -#undef ZF -#undef SF diff --git a/higan/processor/z80/instructions.cpp b/higan/processor/z80/instructions.cpp index dc98495e..da57a1b2 100644 --- a/higan/processor/z80/instructions.cpp +++ b/higan/processor/z80/instructions.cpp @@ -1,5 +1,5 @@ //legend: -// a = r.a +// a = register A // c = condition // e = relative operand // in = (operand) @@ -13,14 +13,14 @@ auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 { uint9 z = x + y + c; - r.p.c = z.bit(8); - r.p.n = 0; - r.p.v = ~(x ^ y) & (x ^ z) & 0x80; - r.p.x = z.bit(3); - r.p.h = (x ^ y ^ z) & 0x10; - r.p.y = z.bit(5); - r.p.z = (uint8)z == 0; - r.p.s = z.bit(7); + CF = z.bit(8); + NF = 0; + VF = ~(x ^ y) & (x ^ z) & 0x80; + XF = z.bit(3); + HF = (x ^ y ^ z) & 0x10; + YF = z.bit(5); + ZF = (uint8)z == 0; + SF = z.bit(7); return z; } @@ -28,14 +28,42 @@ auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 { auto Z80::AND(uint8 x, uint8 y) -> uint8 { uint8 z = x & y; - r.p.c = 0; - r.p.n = 0; - r.p.v = z == 0; - r.p.x = z.bit(3); - r.p.h = 1; - r.p.y = z.bit(5); - r.p.z = z == 0; - r.p.s = z.bit(7); + CF = 0; + NF = 0; + PF = parity(z); + XF = z.bit(3); + HF = 1; + YF = z.bit(5); + ZF = z == 0; + SF = z.bit(7); + + return z; +} + +auto Z80::DEC(uint8 x) -> uint8 { + uint8 z = x - 1; + + NF = 1; + VF = z == 0x7f; + XF = z.bit(3); + HF = z.bits(0,3) == 0x0f; + YF = z.bit(5); + ZF = z == 0; + SF = z.bit(7); + + return z; +} + +auto Z80::INC(uint8 x) -> uint8 { + uint8 z = x + 1; + + NF = 0; + VF = z == 0x80; + XF = z.bit(3); + HF = z.bits(0,3) == 0x00; + YF = z.bit(5); + ZF = z == 0; + SF = z.bit(7); return z; } @@ -43,14 +71,14 @@ auto Z80::AND(uint8 x, uint8 y) -> uint8 { auto Z80::OR(uint8 x, uint8 y) -> uint8 { uint8 z = x | y; - r.p.c = 0; - r.p.n = 0; - r.p.v = z == 0; - r.p.x = z.bit(3); - r.p.h = 0; - r.p.y = z.bit(5); - r.p.z = z == 0; - r.p.s = z.bit(7); + CF = 0; + NF = 0; + PF = parity(z); + XF = z.bit(3); + HF = 0; + YF = z.bit(5); + ZF = z == 0; + SF = z.bit(7); return z; } @@ -58,14 +86,14 @@ auto Z80::OR(uint8 x, uint8 y) -> uint8 { auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 { uint9 z = x - y - c; - r.p.c = z.bit(8); - r.p.n = 1; - r.p.v = (x ^ y) & (x ^ z) & 0x80; - r.p.x = z.bit(3); - r.p.h = (x ^ y ^ z) & 0x10; - r.p.y = z.bit(5); - r.p.z = (uint8)z == 0; - r.p.s = z.bit(7); + CF = z.bit(8); + NF = 1; + VF = (x ^ y) & (x ^ z) & 0x80; + XF = z.bit(3); + HF = (x ^ y ^ z) & 0x10; + YF = z.bit(5); + ZF = (uint8)z == 0; + SF = z.bit(7); return z; } @@ -73,14 +101,14 @@ auto Z80::SUB(uint8 x, uint8 y, bool c) -> uint8 { auto Z80::XOR(uint8 x, uint8 y) -> uint8 { uint8 z = x ^ y; - r.p.c = 0; - r.p.n = 0; - r.p.p = parity(z); - r.p.x = z.bit(3); - r.p.h = 0; - r.p.y = z.bit(5); - r.p.z = z == 0; - r.p.s = z.bit(7); + CF = 0; + NF = 0; + PF = parity(z); + XF = z.bit(3); + HF = 0; + YF = z.bit(5); + ZF = z == 0; + SF = z.bit(7); return z; } @@ -88,39 +116,77 @@ auto Z80::XOR(uint8 x, uint8 y) -> uint8 { // auto Z80::instructionADC_a_irr(uint16& x) -> void { - r.a = ADD(r.a, read(displace(x)), r.p.c); + A = ADD(A, read(displace(x)), CF); } auto Z80::instructionADC_a_r(uint8& x) -> void { - r.a = ADD(r.a, x, r.p.c); + A = ADD(A, x, CF); } auto Z80::instructionADD_a_irr(uint16& x) -> void { - r.a = ADD(r.a, read(displace(x))); + A = ADD(A, read(displace(x))); } auto Z80::instructionADD_a_r(uint8& x) -> void { - r.a = ADD(r.a, x); + A = ADD(A, x); +} + +auto Z80::instructionADD_rr_rr(uint16& x, uint16& y) -> void { + wait(4); + x.byte(0) = ADD(x.byte(0), y.byte(0)); + wait(3); + x.byte(1) = ADD(x.byte(1), y.byte(1), CF); } auto Z80::instructionAND_a_irr(uint16& x) -> void { - r.a = AND(r.a, read(displace(x))); + A = AND(A, read(displace(x))); } auto Z80::instructionAND_a_r(uint8& x) -> void { - r.a = AND(r.a, x); + A = AND(A, x); +} + +auto Z80::instructionCCF() -> void { + CF = !CF; + NF = 0; + HF = !CF; } auto Z80::instructionCP_a_irr(uint16& x) -> void { - SUB(r.a, read(displace(x))); + SUB(A, read(displace(x))); } auto Z80::instructionCP_a_n() -> void { - SUB(r.a, operand()); + SUB(A, operand()); } auto Z80::instructionCP_a_r(uint8& x) -> void { - SUB(r.a, x); + SUB(A, x); +} + +auto Z80::instructionCPL() -> void { + A = ~A; + + NF = 1; + XF = A.bit(3); + HF = 1; + YF = A.bit(5); +} + +auto Z80::instructionDEC_irr(uint16& x) -> void { + auto addr = displace(x); + auto data = read(addr); + wait(1); + write(addr, DEC(data)); +} + +auto Z80::instructionDEC_r(uint8& x) -> void { + x = DEC(x); +} + +auto Z80::instructionDEC_rr(uint16& x) -> void { + wait(2); + x--; } auto Z80::instructionDI() -> void { @@ -133,6 +199,12 @@ auto Z80::instructionEI() -> void { r.iff2 = 1; } +auto Z80::instructionEX_rr_rr(uint16& x, uint16& y) -> void { + auto z = x; + x = y; + y = z; +} + auto Z80::instructionHALT() -> void { r.halt = 1; } @@ -143,7 +215,23 @@ auto Z80::instructionIM_o(uint2 code) -> void { } auto Z80::instructionIN_a_in() -> void { - r.a = in(operand()); + A = in(operand()); +} + +auto Z80::instructionINC_irr(uint16& x) -> void { + auto addr = displace(x); + auto data = read(addr); + wait(1); + write(addr, INC(data)); +} + +auto Z80::instructionINC_r(uint8& x) -> void { + x = INC(x); +} + +auto Z80::instructionINC_rr(uint16& x) -> void { + wait(2); + x++; } auto Z80::instructionJP_c_nn(bool c) -> void { @@ -156,8 +244,26 @@ auto Z80::instructionJR_c_e(bool c) -> void { if(c) wait(5), r.pc += (int8)e; } +auto Z80::instructionLD_a_inn() -> void { + A = read(operands()); +} + +auto Z80::instructionLD_a_irr(uint16& x) -> void { + A = read(displace(x)); +} + auto Z80::instructionLD_inn_a() -> void { - write(operands(), r.a); + write(operands(), A); +} + +auto Z80::instructionLD_inn_rr(uint16& x) -> void { + auto addr = operands(); + write(addr + 0, x >> 0); + write(addr + 1, x >> 8); +} + +auto Z80::instructionLD_irr_a(uint16& x) -> void { + write(displace(x), A); } auto Z80::instructionLD_irr_n(uint16& x) -> void { @@ -181,6 +287,12 @@ auto Z80::instructionLD_r_r(uint8& x, uint8& y) -> void { x = y; } +auto Z80::instructionLD_rr_inn(uint16& x) -> void { + auto addr = operands(); + x.byte(0) = read(addr + 0); + x.byte(1) = read(addr + 1); +} + auto Z80::instructionLD_rr_nn(uint16& x) -> void { x = operands(); } @@ -189,33 +301,83 @@ auto Z80::instructionNOP() -> void { } auto Z80::instructionOR_a_irr(uint16& x) -> void { - r.a = OR(r.a, read(displace(x))); + A = OR(A, read(displace(x))); } auto Z80::instructionOR_a_r(uint8& x) -> void { - r.a = OR(r.a, x); + A = OR(A, x); +} + +auto Z80::instructionRLA() -> void { + bool c = A.bit(7); + A = A << 1 | CF; + + CF = c; + NF = 0; + XF = A.bit(3); + HF = 0; + YF = A.bit(5); +} + +auto Z80::instructionRLCA() -> void { + bool c = A.bit(7); + A = A << 1 | c; + + CF = c; + NF = 0; + XF = A.bit(3); + HF = 0; + YF = A.bit(5); +} + +auto Z80::instructionRRA() -> void { + bool c = A.bit(0); + A = CF << 7 | A >> 1; + + CF = c; + NF = 0; + XF = A.bit(3); + HF = 0; + YF = A.bit(5); +} + +auto Z80::instructionRRCA() -> void { + bool c = A.bit(0); + A = c << 7 | A >> 1; + + CF = c; + NF = 0; + XF = A.bit(3); + HF = 0; + YF = A.bit(5); } auto Z80::instructionSBC_a_irr(uint16& x) -> void { - r.a = SUB(r.a, read(displace(x)), r.p.c); + A = SUB(A, read(displace(x)), CF); } auto Z80::instructionSBC_a_r(uint8& x) -> void { - r.a = SUB(r.a, x, r.p.c); + A = SUB(A, x, CF); +} + +auto Z80::instructionSCF() -> void { + CF = 1; + NF = 0; + HF = 0; } auto Z80::instructionSUB_a_irr(uint16& x) -> void { - r.a = SUB(r.a, read(displace(x))); + A = SUB(A, read(displace(x))); } auto Z80::instructionSUB_a_r(uint8& x) -> void { - r.a = SUB(r.a, x); + A = SUB(A, x); } auto Z80::instructionXOR_a_irr(uint16& x) -> void { - r.a = XOR(r.a, read(displace(x))); + A = XOR(A, read(displace(x))); } auto Z80::instructionXOR_a_r(uint8& x) -> void { - r.a = XOR(r.a, x); + A = XOR(A, x); } diff --git a/higan/processor/z80/memory.cpp b/higan/processor/z80/memory.cpp index aee0dab7..ae958518 100644 --- a/higan/processor/z80/memory.cpp +++ b/higan/processor/z80/memory.cpp @@ -18,7 +18,7 @@ auto Z80::operands() -> uint16 { } auto Z80::displace(uint16& x) -> uint16 { - if(!r.prefix) return x; + if(&x != &r.ix.word && &x != &r.iy.word) return x; auto d = read(x); wait(5); return x + (int8)d; diff --git a/higan/processor/z80/registers.cpp b/higan/processor/z80/registers.cpp new file mode 100644 index 00000000..8533e1e6 --- /dev/null +++ b/higan/processor/z80/registers.cpp @@ -0,0 +1,51 @@ +#define AF r.af.word +#define BC r.bc.word +#define DE r.de.word +#define HL r.hlp->word + +#define A r.af.byte.hi +#define F r.af.byte.lo +#define B r.bc.byte.hi +#define C r.bc.byte.lo +#define D r.de.byte.hi +#define E r.de.byte.lo +#define H r.hlp->byte.hi +#define L r.hlp->byte.lo + +#define _H r.hl.byte.hi +#define _L r.hl.byte.lo +#define _HL r.hl.word + +#define AF_ r.af_.word +#define BC_ r.bc_.word +#define DE_ r.de_.word +#define HL_ r.hl_.word + +#define A_ r.af_.byte.hi +#define F_ r.af_.byte.lo +#define B_ r.bc_.byte.hi +#define C_ r.bc_.byte.lo +#define D_ r.de_.byte.hi +#define E_ r.de_.byte.lo +#define H_ r.hl_.byte.hi +#define L_ r.hl_.byte.lo + +#define SP r.sp +#define PC r.pc + +#define IX r.ix.word +#define IY r.iy.word +#define IR r.ir.word + +#define I r.ir.byte.hi +#define R r.ir.byte.lo + +#define CF r.af.byte.lo.bit(0) +#define NF r.af.byte.lo.bit(1) +#define PF r.af.byte.lo.bit(2) +#define VF r.af.byte.lo.bit(2) +#define XF r.af.byte.lo.bit(3) +#define HF r.af.byte.lo.bit(4) +#define YF r.af.byte.lo.bit(5) +#define ZF r.af.byte.lo.bit(6) +#define SF r.af.byte.lo.bit(7) diff --git a/higan/processor/z80/z80.cpp b/higan/processor/z80/z80.cpp index 763d9acf..7c5117cb 100644 --- a/higan/processor/z80/z80.cpp +++ b/higan/processor/z80/z80.cpp @@ -3,30 +3,18 @@ namespace Processor { +#include "disassembler.cpp" +#include "registers.cpp" #include "memory.cpp" #include "instruction.cpp" #include "instructions.cpp" -#include "disassembler.cpp" auto Z80::power() -> void { } auto Z80::reset() -> void { - r.af = 0x0000; - r.bc = 0x0000; - r.de = 0x0000; - r.hl = 0x0000; - r.ir = 0x0000; - r.ix = 0x0000; - r.iy = 0x0000; - r.sp = 0x0000; - r.pc = 0x0000; - - r.halt = 0; - r.iff1 = 0; - r.iff2 = 0; - r.im = 0; - + memory::fill(&r, sizeof(Registers)); + r.hlp = &r.hl; instructionsExecuted = 0; } diff --git a/higan/processor/z80/z80.hpp b/higan/processor/z80/z80.hpp index 5911303c..2e11c56e 100644 --- a/higan/processor/z80/z80.hpp +++ b/higan/processor/z80/z80.hpp @@ -41,6 +41,8 @@ struct Z80 { //instructions.cpp auto ADD(uint8, uint8, bool = false) -> uint8; auto AND(uint8, uint8) -> uint8; + auto DEC(uint8) -> uint8; + auto INC(uint8) -> uint8; auto OR (uint8, uint8) -> uint8; auto SUB(uint8, uint8, bool = false) -> uint8; auto XOR(uint8, uint8) -> uint8; @@ -49,30 +51,50 @@ struct Z80 { auto instructionADC_a_r(uint8&) -> void; auto instructionADD_a_irr(uint16&) -> void; auto instructionADD_a_r(uint8&) -> void; + auto instructionADD_rr_rr(uint16&, uint16&) -> void; auto instructionAND_a_irr(uint16&) -> void; auto instructionAND_a_r(uint8&) -> void; + auto instructionCCF() -> void; auto instructionCP_a_irr(uint16& x) -> void; auto instructionCP_a_n() -> void; auto instructionCP_a_r(uint8& x) -> void; + auto instructionCPL() -> void; + auto instructionDEC_irr(uint16&) -> void; + auto instructionDEC_r(uint8&) -> void; + auto instructionDEC_rr(uint16&) -> void; auto instructionDI() -> void; auto instructionEI() -> void; + auto instructionEX_rr_rr(uint16&, uint16&) -> void; auto instructionHALT() -> void; auto instructionIM_o(uint2) -> void; auto instructionIN_a_in() -> void; + auto instructionINC_irr(uint16&) -> void; + auto instructionINC_r(uint8&) -> void; + auto instructionINC_rr(uint16&) -> void; auto instructionJP_c_nn(bool) -> void; auto instructionJR_c_e(bool) -> void; + auto instructionLD_a_inn() -> void; + auto instructionLD_a_irr(uint16& x) -> void; auto instructionLD_inn_a() -> void; + auto instructionLD_inn_rr(uint16&) -> void; + auto instructionLD_irr_a(uint16&) -> void; auto instructionLD_irr_n(uint16&) -> void; auto instructionLD_irr_r(uint16&, uint8&) -> void; auto instructionLD_r_n(uint8&) -> void; auto instructionLD_r_irr(uint8&, uint16&) -> void; auto instructionLD_r_r(uint8&, uint8&) -> void; + auto instructionLD_rr_inn(uint16&) -> void; auto instructionLD_rr_nn(uint16&) -> void; auto instructionNOP() -> void; auto instructionOR_a_irr(uint16&) -> void; auto instructionOR_a_r(uint8&) -> void; + auto instructionRLA() -> void; + auto instructionRLCA() -> void; + auto instructionRRA() -> void; + auto instructionRRCA() -> void; auto instructionSBC_a_irr(uint16&) -> void; auto instructionSBC_a_r(uint8&) -> void; + auto instructionSCF() -> void; auto instructionSUB_a_irr(uint16&) -> void; auto instructionSUB_a_r(uint8&) -> void; auto instructionXOR_a_irr(uint16&) -> void; @@ -85,62 +107,28 @@ struct Z80 { auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string; struct Registers { - union { - uint16_t af; - struct { uint8_t order_msb2(a, f); }; - union { - BooleanBitField c; //carry - BooleanBitField n; //add / subtract - BooleanBitField p; //parity - BooleanBitField v; //overflow - BooleanBitField x; //unused (copy of bit 3 of result) - BooleanBitField h; //half-carry - BooleanBitField y; //unused (copy of bit 5 of result) - BooleanBitField z; //zero - BooleanBitField s; //sign - } p; + union Pair { + Pair() : word(0) {} + uint16 word; + struct Byte { uint8 order_msb2(hi, lo); } byte; }; - union { - uint16_t bc; - struct { uint8_t order_msb2(b, c); }; - }; - - union { - uint16_t de; - struct { uint8_t order_msb2(d, e); }; - }; - - union { - uint16_t hl; - struct { uint8_t order_msb2(h, l); }; - }; - - union { - uint16_t ix; - struct { uint8_t order_msb2(ixh, ixl); }; - }; - - union { - uint16_t iy; - struct { uint8_t order_msb2(iyh, iyl); }; - }; - - union { - uint16_t ir; - struct { uint8_t order_msb2(i, r); }; - }; - - uint16_t sp; - uint16_t pc; + Pair af, af_; + Pair bc, bc_; + Pair de, de_; + Pair hl, hl_; + Pair ix; + Pair iy; + Pair ir; + uint16 sp; + uint16 pc; boolean halt; //HALT instruction executed boolean iff1; //interrupt flip-flop 1 boolean iff2; //interrupt flip-flop 2 uint2 im; //interrupt mode (0-2) - uint8 prefix; - uint8 flag; + Pair* hlp = nullptr; } r; Bus* bus = nullptr;