From 2fbbccf9857d0678e74880231b89ad5dbd17d4e7 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 6 Sep 2016 10:09:33 +1000 Subject: [PATCH] Update to v101r16 release. byuu says: Changelog: - Z80: implemented 113 new instructions (all the easy LD/ADC/ADD/AND/OR/SBC/SUB/XOR ones) - Z80: used alternative to castable type (manual cast inside instruction() register macros) - Z80: debugger: used register macros to reduce typing and increase readability - Z80: debugger: smarter way of handling multiple DD/FD prefixes (using gotos, yay!) - ruby: fixed crash with Windows input driver on exit (from SuperMikeMan) I have no idea how the P/V flag is supposed to work on AND/OR/XOR, so that's probably wrong for now. HALT is also mostly a dummy function for now. But I typically implement those inside instruction(), so it probably won't need to be changed? We'll see. --- higan/emulator/emulator.hpp | 2 +- higan/processor/z80/disassembler.cpp | 235 ++++++++++++++++++++++----- higan/processor/z80/instruction.cpp | 165 ++++++++++++++++--- higan/processor/z80/instructions.cpp | 184 +++++++++++++++++---- higan/processor/z80/memory.cpp | 5 + higan/processor/z80/z80.cpp | 1 + higan/processor/z80/z80.hpp | 64 +++++--- ruby/input/keyboard/rawinput.cpp | 3 +- ruby/input/mouse/rawinput.cpp | 1 + 9 files changed, 542 insertions(+), 118 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 7df5326c..ba76d0ab 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.15"; + static const string Version = "101.16"; 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 9885c6af..b76be29e 100644 --- a/higan/processor/z80/disassembler.cpp +++ b/higan/processor/z80/disassembler.cpp @@ -3,16 +3,26 @@ auto Z80::disassemble(uint16 pc) -> string { s.append(hex(pc, 4L), " "); uint8 prefix = 0x00; - while(true) { - auto code = bus->read(pc++); + auto code = bus->read(pc++); + if(code == 0xdd || code == 0xfd) { + prefix = code; + + code = bus->read(pc++); if(code == 0xdd || code == 0xfd) { - prefix = code; - continue; + if(prefix == 0xdd) { + s.append("ix:"); + goto finish; + } + if(prefix == 0xfd) { + s.append("iy:"); + goto finish; + } } - s.append(pad(disassemble__(pc, prefix, code), -18L, ' ')); - break; } + 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)); @@ -30,11 +40,25 @@ auto Z80::disassemble(uint16 pc) -> string { #define IN string{"(", N, ")"} #define NN string{"$", hex(word(), 4L)} #define INN string{"(", NN, ")"} -#define E string{"$", hex(branch(), 4L)} +#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 HD "h" +#define LD "l" + +#define AF "af" +#define BC "bc" +#define DE "de" +#define HL prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl" +#define SP "sp" -#define H string{prefix == 0xdd ? "ixh" : prefix == 0xfd ? "iyh" : "h"} -#define L string{prefix == 0xdd ? "ixl" : prefix == 0xfd ? "iyl" : "l"} -#define HL string{prefix == 0xdd ? "ix" : prefix == 0xfd ? "iy" : "hl"} #define IHL string{"(", HL, displace(), ")"} auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { @@ -63,46 +87,159 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { switch(code) { op(0x00, "nop ") - op(0x01, "ld ", "bc", NN) - op(0x06, "ld ", "b", N) - op(0x0e, "ld ", "c", N) - op(0x11, "ld ", "de", NN) - op(0x16, "ld ", "d", N) - op(0x18, "jr ", E) - op(0x1e, "ld ", "e", N) - op(0x20, "jr ", "nz", E) + op(0x01, "ld ", BC, NN) + op(0x06, "ld ", B, N) + op(0x0e, "ld ", C, N) + op(0x11, "ld ", DE, NN) + op(0x16, "ld ", E, N) + op(0x18, "jr ", R) + op(0x1e, "ld ", E, N) + op(0x20, "jr ", "nz", R) op(0x21, "ld ", HL, NN) op(0x26, "ld ", H, N) - op(0x28, "jr ", "z", E) + op(0x28, "jr ", "z", R) op(0x2e, "ld ", L, N) - op(0x30, "jr ", "nc", E) - op(0x31, "ld ", "sp", NN) - op(0x32, "ld ", INN, "a") + op(0x30, "jr ", "nc", R) + op(0x31, "ld ", SP, NN) + op(0x32, "ld ", INN, A) op(0x36, "ld ", IHL, N) - op(0x38, "jr ", "c", E) - op(0x3e, "ld ", "a", N) - 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(0x77, "ld ", IHL, "a") - op(0xb8, "cp ", "b") - op(0xb9, "cp ", "c") - op(0xba, "cp ", "d") - op(0xbb, "cp ", "e") - op(0xbc, "cp ", H) - op(0xbd, "cp ", L) - op(0xbe, "cp ", IHL) - op(0xbf, "cp ", "a") + op(0x38, "jr ", "c", R) + op(0x3e, "ld ", A, N) + 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 ", HD, 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 ", LD, 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(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(0xdb, "in ", A, IN) op(0xe2, "jp ", "po", NN) op(0xea, "jp ", "pe", NN) op(0xed, "ed: ") @@ -110,7 +247,7 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { op(0xf3, "di ") op(0xfa, "jp ", "m", NN) op(0xfb, "ei ") - op(0xfe, "cp ", N) + op(0xfe, "cp ", A, N) } return {"???: ", hex(code, 2L)}; @@ -143,9 +280,23 @@ auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string { #undef IN #undef NN #undef INN -#undef E +#undef R +#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 IHL diff --git a/higan/processor/z80/instruction.cpp b/higan/processor/z80/instruction.cpp index 116aa61f..7ad9d23a 100644 --- a/higan/processor/z80/instruction.cpp +++ b/higan/processor/z80/instruction.cpp @@ -23,20 +23,22 @@ auto Z80::instruction() -> void { #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); -#define A r.a -#define F r.f -#define B r.b -#define C r.c -#define D r.d -#define E r.e -#define H r.prefix == 0xdd ? r.ixh : r.prefix == 0xfd ? r.iyh : r.h -#define L r.prefix == 0xdd ? r.ixl : r.prefix == 0xfd ? r.iyl : r.l +#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 r.af -#define BC r.bc -#define DE r.de -#define HL r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl -#define SP r.sp +#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 @@ -69,21 +71,134 @@ auto Z80::instruction__(uint8 code) -> void { op(0x36, LD_irr_n, HL) op(0x38, JR_c_e, CF == 1) op(0x3e, LD_r_n, A) + 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, HD, 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, LD, 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, r.h) - op(0x75, LD_irr_r, HL, r.l) + op(0x74, LD_irr_r, HL, HD) + op(0x75, LD_irr_r, HL, LD) + op(0x76, HALT) op(0x77, LD_irr_r, HL, A) - op(0xb8, CP_r, B) - op(0xb9, CP_r, C) - op(0xba, CP_r, D) - op(0xbb, CP_r, E) - op(0xbc, CP_r, H) - op(0xbd, CP_r, L) - op(0xbe, CP_irr, HL) - op(0xbf, CP_r, 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(0xc2, JP_c_nn, ZF == 0) op(0xc3, JP_c_nn, 1) op(0xca, JP_c_nn, ZF == 1) @@ -98,7 +213,7 @@ auto Z80::instruction__(uint8 code) -> void { op(0xf3, DI) op(0xfa, JP_c_nn, SF == 1) op(0xfb, EI) - op(0xfe, CP_n) + op(0xfe, CP_a_n) } trap(0x00, code); @@ -131,6 +246,8 @@ auto Z80::instructionED(uint8 code) -> void { #undef E #undef H #undef L +#undef HD +#undef LD #undef AF #undef BC diff --git a/higan/processor/z80/instructions.cpp b/higan/processor/z80/instructions.cpp index 18001080..dc98495e 100644 --- a/higan/processor/z80/instructions.cpp +++ b/higan/processor/z80/instructions.cpp @@ -1,5 +1,6 @@ //legend: // a = r.a +// c = condition // e = relative operand // in = (operand) // inn = (operand-word) @@ -9,30 +10,117 @@ // nn = operand-word // r = register -auto Z80::CP(uint8 x) -> void { - uint9 y = r.a - x; +auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 { + uint9 z = x + y + c; - r.p.c = y.bit(8); + 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); + + return z; +} + +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); + + return z; +} + +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); + + return z; +} + +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 = (r.a ^ x) & (r.a ^ y) & 0x80; - r.p.x = y.bit(3); - r.p.h = (r.a ^ y ^ x) & 0x10; - r.p.y = y.bit(5); - r.p.z = (uint8)y == 0; - r.p.s = y.bit(7); + 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); + + return z; } -auto Z80::instructionCP_irr(uint16& x) -> void { - auto addr = displace(x); - CP(read(addr)); +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); + + return z; } -auto Z80::instructionCP_n() -> void { - CP(operand()); +// + +auto Z80::instructionADC_a_irr(uint16& x) -> void { + r.a = ADD(r.a, read(displace(x)), r.p.c); } -auto Z80::instructionCP_r(uint8& x) -> void { - CP(x); +auto Z80::instructionADC_a_r(uint8& x) -> void { + r.a = ADD(r.a, x, r.p.c); +} + +auto Z80::instructionADD_a_irr(uint16& x) -> void { + r.a = ADD(r.a, read(displace(x))); +} + +auto Z80::instructionADD_a_r(uint8& x) -> void { + r.a = ADD(r.a, x); +} + +auto Z80::instructionAND_a_irr(uint16& x) -> void { + r.a = AND(r.a, read(displace(x))); +} + +auto Z80::instructionAND_a_r(uint8& x) -> void { + r.a = AND(r.a, x); +} + +auto Z80::instructionCP_a_irr(uint16& x) -> void { + SUB(r.a, read(displace(x))); +} + +auto Z80::instructionCP_a_n() -> void { + SUB(r.a, operand()); +} + +auto Z80::instructionCP_a_r(uint8& x) -> void { + SUB(r.a, x); } auto Z80::instructionDI() -> void { @@ -45,6 +133,10 @@ auto Z80::instructionEI() -> void { r.iff2 = 1; } +auto Z80::instructionHALT() -> void { + r.halt = 1; +} + auto Z80::instructionIM_o(uint2 code) -> void { wait(4); r.im = code; @@ -55,22 +147,17 @@ auto Z80::instructionIN_a_in() -> void { } auto Z80::instructionJP_c_nn(bool c) -> void { - auto lo = operand(); - auto hi = operand(); - if(c) r.pc = hi << 8 | lo << 0; + auto pc = operands(); + if(c) r.pc = pc; } auto Z80::instructionJR_c_e(bool c) -> void { auto e = operand(); - if(!c) return; - wait(5); - r.pc += (int8)e; + if(c) wait(5), r.pc += (int8)e; } auto Z80::instructionLD_inn_a() -> void { - auto lo = operand(); - auto hi = operand(); - write(hi << 8 | lo << 0, r.a); + write(operands(), r.a); } auto Z80::instructionLD_irr_n(uint16& x) -> void { @@ -79,19 +166,56 @@ auto Z80::instructionLD_irr_n(uint16& x) -> void { } auto Z80::instructionLD_irr_r(uint16& x, uint8& y) -> void { - auto addr = displace(x); - write(addr, y); + write(displace(x), y); } auto Z80::instructionLD_r_n(uint8& x) -> void { x = operand(); } +auto Z80::instructionLD_r_irr(uint8& x, uint16& y) -> void { + x = read(displace(y)); +} + +auto Z80::instructionLD_r_r(uint8& x, uint8& y) -> void { + x = y; +} + auto Z80::instructionLD_rr_nn(uint16& x) -> void { - auto lo = operand(); - auto hi = operand(); - x = hi << 8 | lo << 0; + x = operands(); } auto Z80::instructionNOP() -> void { } + +auto Z80::instructionOR_a_irr(uint16& x) -> void { + r.a = OR(r.a, read(displace(x))); +} + +auto Z80::instructionOR_a_r(uint8& x) -> void { + r.a = OR(r.a, x); +} + +auto Z80::instructionSBC_a_irr(uint16& x) -> void { + r.a = SUB(r.a, read(displace(x)), r.p.c); +} + +auto Z80::instructionSBC_a_r(uint8& x) -> void { + r.a = SUB(r.a, x, r.p.c); +} + +auto Z80::instructionSUB_a_irr(uint16& x) -> void { + r.a = SUB(r.a, read(displace(x))); +} + +auto Z80::instructionSUB_a_r(uint8& x) -> void { + r.a = SUB(r.a, x); +} + +auto Z80::instructionXOR_a_irr(uint16& x) -> void { + r.a = XOR(r.a, read(displace(x))); +} + +auto Z80::instructionXOR_a_r(uint8& x) -> void { + r.a = XOR(r.a, x); +} diff --git a/higan/processor/z80/memory.cpp b/higan/processor/z80/memory.cpp index 443fe649..aee0dab7 100644 --- a/higan/processor/z80/memory.cpp +++ b/higan/processor/z80/memory.cpp @@ -12,6 +12,11 @@ auto Z80::operand() -> uint8 { return bus->read(r.pc++); } +auto Z80::operands() -> uint16 { + uint16 data = operand() << 0; + return data | operand() << 8; +} + auto Z80::displace(uint16& x) -> uint16 { if(!r.prefix) return x; auto d = read(x); diff --git a/higan/processor/z80/z80.cpp b/higan/processor/z80/z80.cpp index f6e1b0c0..763d9acf 100644 --- a/higan/processor/z80/z80.cpp +++ b/higan/processor/z80/z80.cpp @@ -22,6 +22,7 @@ auto Z80::reset() -> void { r.sp = 0x0000; r.pc = 0x0000; + r.halt = 0; r.iff1 = 0; r.iff2 = 0; r.im = 0; diff --git a/higan/processor/z80/z80.hpp b/higan/processor/z80/z80.hpp index f59eba4f..5911303c 100644 --- a/higan/processor/z80/z80.hpp +++ b/higan/processor/z80/z80.hpp @@ -24,6 +24,7 @@ struct Z80 { auto wait(uint clocks = 1) -> void; auto opcode() -> uint8; auto operand() -> uint8; + auto operands() -> uint16; auto displace(uint16&) -> uint16; auto read(uint16 addr) -> uint8; auto write(uint16 addr, uint8 data) -> void; @@ -38,12 +39,24 @@ struct Z80 { auto instructionED(uint8 code) -> void; //instructions.cpp - auto CP(uint8) -> void; - auto instructionCP_irr(uint16& x) -> void; - auto instructionCP_n() -> void; - auto instructionCP_r(uint8& x) -> void; + auto ADD(uint8, uint8, bool = false) -> uint8; + auto AND(uint8, uint8) -> uint8; + auto OR (uint8, uint8) -> uint8; + auto SUB(uint8, uint8, bool = false) -> uint8; + auto XOR(uint8, uint8) -> uint8; + + auto instructionADC_a_irr(uint16&) -> void; + auto instructionADC_a_r(uint8&) -> void; + auto instructionADD_a_irr(uint16&) -> void; + auto instructionADD_a_r(uint8&) -> void; + auto instructionAND_a_irr(uint16&) -> void; + auto instructionAND_a_r(uint8&) -> void; + auto instructionCP_a_irr(uint16& x) -> void; + auto instructionCP_a_n() -> void; + auto instructionCP_a_r(uint8& x) -> void; auto instructionDI() -> void; auto instructionEI() -> void; + auto instructionHALT() -> void; auto instructionIM_o(uint2) -> void; auto instructionIN_a_in() -> void; auto instructionJP_c_nn(bool) -> void; @@ -52,8 +65,18 @@ struct Z80 { 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_nn(uint16&) -> void; auto instructionNOP() -> void; + auto instructionOR_a_irr(uint16&) -> void; + auto instructionOR_a_r(uint8&) -> void; + auto instructionSBC_a_irr(uint16&) -> void; + auto instructionSBC_a_r(uint8&) -> void; + auto instructionSUB_a_irr(uint16&) -> void; + auto instructionSUB_a_r(uint8&) -> void; + auto instructionXOR_a_irr(uint16&) -> void; + auto instructionXOR_a_r(uint8&) -> void; //disassembler.cpp auto disassemble(uint16 pc) -> string; @@ -63,8 +86,8 @@ struct Z80 { struct Registers { union { - castable af; - struct { castable order_msb2(a, f); }; + uint16_t af; + struct { uint8_t order_msb2(a, f); }; union { BooleanBitField c; //carry BooleanBitField n; //add / subtract @@ -79,38 +102,39 @@ struct Z80 { }; union { - castable bc; - struct { castable order_msb2(b, c); }; + uint16_t bc; + struct { uint8_t order_msb2(b, c); }; }; union { - castable de; - struct { castable order_msb2(d, e); }; + uint16_t de; + struct { uint8_t order_msb2(d, e); }; }; union { - castable hl; - struct { castable order_msb2(h, l); }; + uint16_t hl; + struct { uint8_t order_msb2(h, l); }; }; union { - castable ix; - struct { castable order_msb2(ixh, ixl); }; + uint16_t ix; + struct { uint8_t order_msb2(ixh, ixl); }; }; union { - castable iy; - struct { castable order_msb2(iyh, iyl); }; + uint16_t iy; + struct { uint8_t order_msb2(iyh, iyl); }; }; union { - castable ir; - struct { castable order_msb2(i, r); }; + uint16_t ir; + struct { uint8_t order_msb2(i, r); }; }; - uint16 sp; - uint16 pc; + uint16_t sp; + uint16_t pc; + boolean halt; //HALT instruction executed boolean iff1; //interrupt flip-flop 1 boolean iff2; //interrupt flip-flop 2 uint2 im; //interrupt mode (0-2) diff --git a/ruby/input/keyboard/rawinput.cpp b/ruby/input/keyboard/rawinput.cpp index 2f77b501..0ad1441b 100644 --- a/ruby/input/keyboard/rawinput.cpp +++ b/ruby/input/keyboard/rawinput.cpp @@ -170,7 +170,8 @@ struct InputKeyboardRawInput { return true; } - void term() { + auto term() -> void { + rawinput.updateKeyboard.reset(); } }; diff --git a/ruby/input/mouse/rawinput.cpp b/ruby/input/mouse/rawinput.cpp index bd25c3fe..671ee46a 100644 --- a/ruby/input/mouse/rawinput.cpp +++ b/ruby/input/mouse/rawinput.cpp @@ -115,6 +115,7 @@ struct InputMouseRawInput { } auto term() -> void { + rawinput.updateMouse.reset(); release(); } };