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<To, With> 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.
This commit is contained in:
Tim Allen 2016-09-06 10:09:33 +10:00
parent 4c3f58150c
commit 2fbbccf985
9 changed files with 542 additions and 118 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@ -3,16 +3,26 @@ auto Z80::disassemble(uint16 pc) -> string {
s.append(hex(pc, 4L), " "); s.append(hex(pc, 4L), " ");
uint8 prefix = 0x00; 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) { if(code == 0xdd || code == 0xfd) {
prefix = code; if(prefix == 0xdd) {
continue; 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(" AF:", hex(r.af, 4L));
s.append(" BC:", hex(r.bc, 4L)); s.append(" BC:", hex(r.bc, 4L));
s.append(" DE:", hex(r.de, 4L)); s.append(" DE:", hex(r.de, 4L));
@ -30,11 +40,25 @@ auto Z80::disassemble(uint16 pc) -> string {
#define IN string{"(", N, ")"} #define IN string{"(", N, ")"}
#define NN string{"$", hex(word(), 4L)} #define NN string{"$", hex(word(), 4L)}
#define INN string{"(", NN, ")"} #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(), ")"} #define IHL string{"(", HL, displace(), ")"}
auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { 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) { switch(code) {
op(0x00, "nop ") op(0x00, "nop ")
op(0x01, "ld ", "bc", NN) op(0x01, "ld ", BC, NN)
op(0x06, "ld ", "b", N) op(0x06, "ld ", B, N)
op(0x0e, "ld ", "c", N) op(0x0e, "ld ", C, N)
op(0x11, "ld ", "de", NN) op(0x11, "ld ", DE, NN)
op(0x16, "ld ", "d", N) op(0x16, "ld ", E, N)
op(0x18, "jr ", E) op(0x18, "jr ", R)
op(0x1e, "ld ", "e", N) op(0x1e, "ld ", E, N)
op(0x20, "jr ", "nz", E) op(0x20, "jr ", "nz", R)
op(0x21, "ld ", HL, NN) op(0x21, "ld ", HL, NN)
op(0x26, "ld ", H, N) op(0x26, "ld ", H, N)
op(0x28, "jr ", "z", E) op(0x28, "jr ", "z", R)
op(0x2e, "ld ", L, N) op(0x2e, "ld ", L, N)
op(0x30, "jr ", "nc", E) op(0x30, "jr ", "nc", R)
op(0x31, "ld ", "sp", NN) op(0x31, "ld ", SP, NN)
op(0x32, "ld ", INN, "a") op(0x32, "ld ", INN, A)
op(0x36, "ld ", IHL, N) op(0x36, "ld ", IHL, N)
op(0x38, "jr ", "c", E) op(0x38, "jr ", "c", R)
op(0x3e, "ld ", "a", N) op(0x3e, "ld ", A, N)
op(0x70, "ld ", IHL, "b") op(0x40, "ld ", B, B)
op(0x71, "ld ", IHL, "c") op(0x41, "ld ", B, C)
op(0x72, "ld ", IHL, "d") op(0x42, "ld ", B, D)
op(0x73, "ld ", IHL, "e") op(0x43, "ld ", B, E)
op(0x74, "ld ", IHL, "h") op(0x44, "ld ", B, H)
op(0x75, "ld ", IHL, "l") op(0x45, "ld ", B, L)
op(0x77, "ld ", IHL, "a") op(0x46, "ld ", B, IHL)
op(0xb8, "cp ", "b") op(0x47, "ld ", B, A)
op(0xb9, "cp ", "c") op(0x48, "ld ", C, B)
op(0xba, "cp ", "d") op(0x49, "ld ", C, C)
op(0xbb, "cp ", "e") op(0x4a, "ld ", C, D)
op(0xbc, "cp ", H) op(0x4b, "ld ", C, E)
op(0xbd, "cp ", L) op(0x4c, "ld ", C, H)
op(0xbe, "cp ", IHL) op(0x4d, "ld ", C, L)
op(0xbf, "cp ", "a") 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(0xc2, "jp ", "nz", NN)
op(0xc3, "jp ", NN) op(0xc3, "jp ", NN)
op(0xca, "jp ", "z", NN) op(0xca, "jp ", "z", NN)
op(0xcb, "cb: ") op(0xcb, "cb: ")
op(0xd2, "jp ", "nc", NN) op(0xd2, "jp ", "nc", NN)
op(0xda, "jp ", "c", NN) op(0xda, "jp ", "c", NN)
op(0xdb, "in ", "a", IN) op(0xdb, "in ", A, IN)
op(0xe2, "jp ", "po", NN) op(0xe2, "jp ", "po", NN)
op(0xea, "jp ", "pe", NN) op(0xea, "jp ", "pe", NN)
op(0xed, "ed: ") op(0xed, "ed: ")
@ -110,7 +247,7 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string {
op(0xf3, "di ") op(0xf3, "di ")
op(0xfa, "jp ", "m", NN) op(0xfa, "jp ", "m", NN)
op(0xfb, "ei ") op(0xfb, "ei ")
op(0xfe, "cp ", N) op(0xfe, "cp ", A, N)
} }
return {"???: ", hex(code, 2L)}; return {"???: ", hex(code, 2L)};
@ -143,9 +280,23 @@ auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string {
#undef IN #undef IN
#undef NN #undef NN
#undef INN #undef INN
#undef E #undef R
#undef A
#undef F
#undef B
#undef C
#undef D
#undef E
#undef H #undef H
#undef L #undef L
#undef HD
#undef LD
#undef AF
#undef BC
#undef DE
#undef HL #undef HL
#undef SP
#undef IHL #undef IHL

View File

@ -23,20 +23,22 @@ auto Z80::instruction() -> void {
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
#define A r.a #define A (uint8&)(r.a)
#define F r.f #define F (uint8&)(r.f)
#define B r.b #define B (uint8&)(r.b)
#define C r.c #define C (uint8&)(r.c)
#define D r.d #define D (uint8&)(r.d)
#define E r.e #define E (uint8&)(r.e)
#define H r.prefix == 0xdd ? r.ixh : r.prefix == 0xfd ? r.iyh : r.h #define H (uint8&)(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 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 AF (uint16&)(r.af)
#define BC r.bc #define BC (uint16&)(r.bc)
#define DE r.de #define DE (uint16&)(r.de)
#define HL r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl #define HL (uint16&)(r.prefix == 0xdd ? r.ix : r.prefix == 0xfd ? r.iy : r.hl)
#define SP r.sp #define SP (uint16&)(r.sp)
#define CF r.p.c #define CF r.p.c
#define NF r.p.n #define NF r.p.n
@ -69,21 +71,134 @@ auto Z80::instruction__(uint8 code) -> void {
op(0x36, LD_irr_n, HL) op(0x36, LD_irr_n, HL)
op(0x38, JR_c_e, CF == 1) op(0x38, JR_c_e, CF == 1)
op(0x3e, LD_r_n, A) 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(0x70, LD_irr_r, HL, B)
op(0x71, LD_irr_r, HL, C) op(0x71, LD_irr_r, HL, C)
op(0x72, LD_irr_r, HL, D) op(0x72, LD_irr_r, HL, D)
op(0x73, LD_irr_r, HL, E) op(0x73, LD_irr_r, HL, E)
op(0x74, LD_irr_r, HL, r.h) op(0x74, LD_irr_r, HL, HD)
op(0x75, LD_irr_r, HL, r.l) op(0x75, LD_irr_r, HL, LD)
op(0x76, HALT)
op(0x77, LD_irr_r, HL, A) op(0x77, LD_irr_r, HL, A)
op(0xb8, CP_r, B) op(0x78, LD_r_r, A, B)
op(0xb9, CP_r, C) op(0x79, LD_r_r, A, C)
op(0xba, CP_r, D) op(0x7a, LD_r_r, A, D)
op(0xbb, CP_r, E) op(0x7b, LD_r_r, A, E)
op(0xbc, CP_r, H) op(0x7c, LD_r_r, A, H)
op(0xbd, CP_r, L) op(0x7d, LD_r_r, A, L)
op(0xbe, CP_irr, HL) op(0x7e, LD_r_irr, A, HL)
op(0xbf, CP_r, A) 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(0xc2, JP_c_nn, ZF == 0)
op(0xc3, JP_c_nn, 1) op(0xc3, JP_c_nn, 1)
op(0xca, JP_c_nn, ZF == 1) op(0xca, JP_c_nn, ZF == 1)
@ -98,7 +213,7 @@ auto Z80::instruction__(uint8 code) -> void {
op(0xf3, DI) op(0xf3, DI)
op(0xfa, JP_c_nn, SF == 1) op(0xfa, JP_c_nn, SF == 1)
op(0xfb, EI) op(0xfb, EI)
op(0xfe, CP_n) op(0xfe, CP_a_n)
} }
trap(0x00, code); trap(0x00, code);
@ -131,6 +246,8 @@ auto Z80::instructionED(uint8 code) -> void {
#undef E #undef E
#undef H #undef H
#undef L #undef L
#undef HD
#undef LD
#undef AF #undef AF
#undef BC #undef BC

View File

@ -1,5 +1,6 @@
//legend: //legend:
// a = r.a // a = r.a
// c = condition
// e = relative operand // e = relative operand
// in = (operand) // in = (operand)
// inn = (operand-word) // inn = (operand-word)
@ -9,30 +10,117 @@
// nn = operand-word // nn = operand-word
// r = register // r = register
auto Z80::CP(uint8 x) -> void { auto Z80::ADD(uint8 x, uint8 y, bool c) -> uint8 {
uint9 y = r.a - x; 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.n = 1;
r.p.v = (r.a ^ x) & (r.a ^ y) & 0x80; r.p.v = (x ^ y) & (x ^ z) & 0x80;
r.p.x = y.bit(3); r.p.x = z.bit(3);
r.p.h = (r.a ^ y ^ x) & 0x10; r.p.h = (x ^ y ^ z) & 0x10;
r.p.y = y.bit(5); r.p.y = z.bit(5);
r.p.z = (uint8)y == 0; r.p.z = (uint8)z == 0;
r.p.s = y.bit(7); r.p.s = z.bit(7);
return z;
} }
auto Z80::instructionCP_irr(uint16& x) -> void { auto Z80::XOR(uint8 x, uint8 y) -> uint8 {
auto addr = displace(x); uint8 z = x ^ y;
CP(read(addr));
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 { auto Z80::instructionADC_a_r(uint8& x) -> void {
CP(x); 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 { auto Z80::instructionDI() -> void {
@ -45,6 +133,10 @@ auto Z80::instructionEI() -> void {
r.iff2 = 1; r.iff2 = 1;
} }
auto Z80::instructionHALT() -> void {
r.halt = 1;
}
auto Z80::instructionIM_o(uint2 code) -> void { auto Z80::instructionIM_o(uint2 code) -> void {
wait(4); wait(4);
r.im = code; r.im = code;
@ -55,22 +147,17 @@ auto Z80::instructionIN_a_in() -> void {
} }
auto Z80::instructionJP_c_nn(bool c) -> void { auto Z80::instructionJP_c_nn(bool c) -> void {
auto lo = operand(); auto pc = operands();
auto hi = operand(); if(c) r.pc = pc;
if(c) r.pc = hi << 8 | lo << 0;
} }
auto Z80::instructionJR_c_e(bool c) -> void { auto Z80::instructionJR_c_e(bool c) -> void {
auto e = operand(); auto e = operand();
if(!c) return; if(c) wait(5), r.pc += (int8)e;
wait(5);
r.pc += (int8)e;
} }
auto Z80::instructionLD_inn_a() -> void { auto Z80::instructionLD_inn_a() -> void {
auto lo = operand(); write(operands(), r.a);
auto hi = operand();
write(hi << 8 | lo << 0, r.a);
} }
auto Z80::instructionLD_irr_n(uint16& x) -> void { 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 Z80::instructionLD_irr_r(uint16& x, uint8& y) -> void {
auto addr = displace(x); write(displace(x), y);
write(addr, y);
} }
auto Z80::instructionLD_r_n(uint8& x) -> void { auto Z80::instructionLD_r_n(uint8& x) -> void {
x = operand(); 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 Z80::instructionLD_rr_nn(uint16& x) -> void {
auto lo = operand(); x = operands();
auto hi = operand();
x = hi << 8 | lo << 0;
} }
auto Z80::instructionNOP() -> void { 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);
}

View File

@ -12,6 +12,11 @@ auto Z80::operand() -> uint8 {
return bus->read(r.pc++); return bus->read(r.pc++);
} }
auto Z80::operands() -> uint16 {
uint16 data = operand() << 0;
return data | operand() << 8;
}
auto Z80::displace(uint16& x) -> uint16 { auto Z80::displace(uint16& x) -> uint16 {
if(!r.prefix) return x; if(!r.prefix) return x;
auto d = read(x); auto d = read(x);

View File

@ -22,6 +22,7 @@ auto Z80::reset() -> void {
r.sp = 0x0000; r.sp = 0x0000;
r.pc = 0x0000; r.pc = 0x0000;
r.halt = 0;
r.iff1 = 0; r.iff1 = 0;
r.iff2 = 0; r.iff2 = 0;
r.im = 0; r.im = 0;

View File

@ -24,6 +24,7 @@ struct Z80 {
auto wait(uint clocks = 1) -> void; auto wait(uint clocks = 1) -> void;
auto opcode() -> uint8; auto opcode() -> uint8;
auto operand() -> uint8; auto operand() -> uint8;
auto operands() -> uint16;
auto displace(uint16&) -> uint16; auto displace(uint16&) -> uint16;
auto read(uint16 addr) -> uint8; auto read(uint16 addr) -> uint8;
auto write(uint16 addr, uint8 data) -> void; auto write(uint16 addr, uint8 data) -> void;
@ -38,12 +39,24 @@ struct Z80 {
auto instructionED(uint8 code) -> void; auto instructionED(uint8 code) -> void;
//instructions.cpp //instructions.cpp
auto CP(uint8) -> void; auto ADD(uint8, uint8, bool = false) -> uint8;
auto instructionCP_irr(uint16& x) -> void; auto AND(uint8, uint8) -> uint8;
auto instructionCP_n() -> void; auto OR (uint8, uint8) -> uint8;
auto instructionCP_r(uint8& x) -> void; 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 instructionDI() -> void;
auto instructionEI() -> void; auto instructionEI() -> void;
auto instructionHALT() -> void;
auto instructionIM_o(uint2) -> void; auto instructionIM_o(uint2) -> void;
auto instructionIN_a_in() -> void; auto instructionIN_a_in() -> void;
auto instructionJP_c_nn(bool) -> void; auto instructionJP_c_nn(bool) -> void;
@ -52,8 +65,18 @@ struct Z80 {
auto instructionLD_irr_n(uint16&) -> void; auto instructionLD_irr_n(uint16&) -> void;
auto instructionLD_irr_r(uint16&, uint8&) -> void; auto instructionLD_irr_r(uint16&, uint8&) -> void;
auto instructionLD_r_n(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 instructionLD_rr_nn(uint16&) -> void;
auto instructionNOP() -> 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 //disassembler.cpp
auto disassemble(uint16 pc) -> string; auto disassemble(uint16 pc) -> string;
@ -63,8 +86,8 @@ struct Z80 {
struct Registers { struct Registers {
union { union {
castable<uint16, uint16_t> af; uint16_t af;
struct { castable<uint8, uint8_t> order_msb2(a, f); }; struct { uint8_t order_msb2(a, f); };
union { union {
BooleanBitField<uint16_t, 0> c; //carry BooleanBitField<uint16_t, 0> c; //carry
BooleanBitField<uint16_t, 1> n; //add / subtract BooleanBitField<uint16_t, 1> n; //add / subtract
@ -79,38 +102,39 @@ struct Z80 {
}; };
union { union {
castable<uint16, uint16_t> bc; uint16_t bc;
struct { castable<uint8, uint8_t> order_msb2(b, c); }; struct { uint8_t order_msb2(b, c); };
}; };
union { union {
castable<uint16, uint16_t> de; uint16_t de;
struct { castable<uint8, uint8_t> order_msb2(d, e); }; struct { uint8_t order_msb2(d, e); };
}; };
union { union {
castable<uint16, uint16_t> hl; uint16_t hl;
struct { castable<uint8, uint8_t> order_msb2(h, l); }; struct { uint8_t order_msb2(h, l); };
}; };
union { union {
castable<uint16, uint16_t> ix; uint16_t ix;
struct { castable<uint8, uint8_t> order_msb2(ixh, ixl); }; struct { uint8_t order_msb2(ixh, ixl); };
}; };
union { union {
castable<uint16, uint16_t> iy; uint16_t iy;
struct { castable<uint8, uint8_t> order_msb2(iyh, iyl); }; struct { uint8_t order_msb2(iyh, iyl); };
}; };
union { union {
castable<uint16, uint16_t> ir; uint16_t ir;
struct { castable<uint8, uint8_t> order_msb2(i, r); }; struct { uint8_t order_msb2(i, r); };
}; };
uint16 sp; uint16_t sp;
uint16 pc; uint16_t pc;
boolean halt; //HALT instruction executed
boolean iff1; //interrupt flip-flop 1 boolean iff1; //interrupt flip-flop 1
boolean iff2; //interrupt flip-flop 2 boolean iff2; //interrupt flip-flop 2
uint2 im; //interrupt mode (0-2) uint2 im; //interrupt mode (0-2)

View File

@ -170,7 +170,8 @@ struct InputKeyboardRawInput {
return true; return true;
} }
void term() { auto term() -> void {
rawinput.updateKeyboard.reset();
} }
}; };

View File

@ -115,6 +115,7 @@ struct InputMouseRawInput {
} }
auto term() -> void { auto term() -> void {
rawinput.updateMouse.reset();
release(); release();
} }
}; };