From dd4a4dc23bcade25a2f7e089a91f6ea0f9848df2 Mon Sep 17 00:00:00 2001 From: Stephen Crane Date: Sun, 3 Mar 2019 12:12:38 +0000 Subject: [PATCH] parity table calculation; z80 flags fixes --- i8080.cpp | 18 +++++++----------- i8080.h | 4 ++-- z80.cpp | 57 +++++++++++++++++++++++++++++++++++-------------------- z80.h | 8 ++++---- 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/i8080.cpp b/i8080.cpp index 8fdcad9..ceef41e 100644 --- a/i8080.cpp +++ b/i8080.cpp @@ -84,17 +84,13 @@ void i8080::daa() { flags.C = c; } -const uint8_t partab[] PROGMEM = { - 0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, - 0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, - 0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, - 0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, -}; - -uint8_t parity_tbl(uint8_t r) { - uint8_t i = r / 8, b = pgm_read_byte(partab + i); - uint8_t m = (1 << (r % 8)); - return m == (b & m); +uint8_t parity(uint8_t r) { + uint8_t c = 0; + while (r) { + r &= (r-1); + c++; + } + return !(c & 1); } void i8080::_op(uint8_t op) { diff --git a/i8080.h b/i8080.h index 87bb9c9..b8ec31f 100644 --- a/i8080.h +++ b/i8080.h @@ -5,7 +5,7 @@ #undef PC #undef SP -uint8_t parity_tbl(uint8_t); +uint8_t parity(uint8_t); class i8080: public CPU { public: @@ -76,7 +76,7 @@ private: inline void _szp(uint8_t r) { flags.S = ((r & 0x80) != 0); flags.Z = (r == 0); - flags.P = parity_tbl(r); + flags.P = parity(r); } inline void _szhp(uint8_t b, uint8_t r) { diff --git a/z80.cpp b/z80.cpp index 02ac84a..560c3b7 100644 --- a/z80.cpp +++ b/z80.cpp @@ -136,7 +136,7 @@ void z80::daa() { else _add(a); flags.C = c; - flags.P = parity_table(A); + flags.P = parity(A); } void z80::_step_idx(EXT_OP f) { @@ -603,6 +603,7 @@ void z80::ed() { SP = _rwPC(); break; case 0xa0: + // ldi b = _rb(HL); BC--; _sb(DE, b); @@ -617,6 +618,7 @@ void z80::ed() { flags.N = flags.H = 0; break; case 0xa1: + // cpi b = _rb(HL); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -635,6 +637,7 @@ void z80::ed() { _memptr++; break; case 0xa2: + // ini _mc(IR, 1); b = _inr(BC); _sb(HL, b); @@ -643,10 +646,11 @@ void z80::ed() { c = b + C + 1; flags.N = (b & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); break; case 0xa3: + // outi _mc(IR, 1); b = _rb(HL); B--; @@ -655,10 +659,11 @@ void z80::ed() { c = b + L; flags.N = (b & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); break; case 0xa8: + // ldd b = _rb(HL); BC--; _sb(DE, b); @@ -673,6 +678,7 @@ void z80::ed() { flags.N = flags.H = 0; break; case 0xa9: + // cpd b = _rb(HL); c = A - b - flags.H; _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -687,6 +693,7 @@ void z80::ed() { // FIXME: flag H break; case 0xaa: + // ind _mc(IR, 1); b = _inr(BC); _memptr = BC-1; @@ -696,10 +703,11 @@ void z80::ed() { c = b + C - 1; flags.N = (b & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); break; case 0xab: + // outd _mc(IR, 1); b = _rb(HL); B--; @@ -709,10 +717,11 @@ void z80::ed() { c = b + L; flags.N = (b & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); break; case 0xb0: + // ldir b = _rb(HL); BC--; _sb(DE, b); @@ -721,6 +730,7 @@ void z80::ed() { b += A; flags.P = (BC != 0); _35(b); + flags._5 = ((b & 0x02) != 0); flags.N = flags.H = 0; if (BC) { _mc(DE, 1); _mc(DE, 1); _mc(DE, 1); @@ -732,6 +742,7 @@ void z80::ed() { HL++; break; case 0xb1: + // cpir b = _rb(HL); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -739,12 +750,13 @@ void z80::ed() { f = (flags.C != 0); _sub(b); BC--; - b = A; + b -= A; A = c; flags.C = f; flags.P = (BC != 0); if (flags.H) b--; _35(b); + flags._5 = ((b & 0x02) != 0); _memptr++; if (!flags.Z) { _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -755,6 +767,7 @@ void z80::ed() { HL++; break; case 0xb2: + // inir _mc(IR, 1); b = _inr(BC); _sb(HL, b); @@ -762,7 +775,7 @@ void z80::ed() { c = b + flags.C + 1; flags.N = (c & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); if (B) { _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -772,6 +785,7 @@ void z80::ed() { HL++; break; case 0xb3: + // outir _mc(IR, 1); b = _rb(HL); B--; @@ -780,7 +794,7 @@ void z80::ed() { c = b + L; flags.N = (b & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); if (B) { _mc(BC, 1); _mc(BC, 1); _mc(BC, 1); @@ -789,6 +803,7 @@ void z80::ed() { } break; case 0xb8: + // lddr b = _rb(HL); BC--; _sb(DE, b); @@ -809,6 +824,7 @@ void z80::ed() { HL--; break; case 0xb9: + // cpdr b = _rb(HL); c = A - b; _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -829,6 +845,7 @@ void z80::ed() { HL--; break; case 0xba: + // indr _mc(IR, 1); b = _inr(BC); _memptr = BC-1; @@ -837,7 +854,7 @@ void z80::ed() { c = b + flags.C + 1; flags.N = (c & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); if (B) { _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); @@ -847,6 +864,7 @@ void z80::ed() { HL--; break; case 0xbb: + // outdr _mc(IR, 1); b = _rb(HL); B--; @@ -856,7 +874,7 @@ void z80::ed() { c = b + L; flags.N = (b & 0x80) != 0; flags.C = flags.H = (c < b); - flags.P = parity_table((c & 0x07) ^ B); + flags.P = parity((c & 0x07) ^ B); _sz35(B); if (B) { _mc(BC, 1); _mc(BC, 1); _mc(BC, 1); @@ -867,17 +885,14 @@ void z80::ed() { } } -const uint8_t partab[] PROGMEM = { - 0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, - 0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, - 0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, - 0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, -}; - -uint8_t z80::parity_table(uint8_t r) { - uint8_t i = r / 8, b = pgm_read_byte(partab + i); - uint8_t m = (1 << (r % 8)); - return m == (b & m); +// kernighan's algorithm +uint8_t z80::parity(uint8_t r) { + uint8_t c = 0; + while (r) { + r &= (r-1); + c++; + } + return !(c & 1); } void z80::cb() { diff --git a/z80.h b/z80.h index e418e87..e35f5b4 100644 --- a/z80.h +++ b/z80.h @@ -148,7 +148,7 @@ private: int _irq_pending; PortDevice *_ports; - uint8_t parity_table(uint8_t); + uint8_t parity(uint8_t); inline uint8_t _rb(Memory::address a) { #if defined(CPU_DEBUG) @@ -222,7 +222,7 @@ private: inline void _szp35(uint8_t r) { _sz35(r); - flags.P = parity_table(r); + flags.P = parity(r); } inline void _inc(uint8_t &b) { @@ -500,7 +500,7 @@ private: inline void inca() { _inc(A); } inline void deca() { _dec(A); } inline void lda() { A = _rb(PC++); } - inline void ccf() { flags.C = !flags.C; flags.N = 0; _35(A); } + inline void ccf() { flags.H = flags.C; flags.C = flags.N = 0; _35(A); } // 0x40 inline void ldbb() {} @@ -937,7 +937,7 @@ private: } inline void _bitHL(int i) { - uint8_t b = _rb(HL); _mc(HL, 1); _bit(i, b); + uint8_t b = _rb(HL); _mc(HL, 1); _bit(i, b); _35(MPH); } inline void bit0b() { _bit(0, B); }