parity table calculation; z80 flags fixes

This commit is contained in:
Stephen Crane 2019-03-03 12:12:38 +00:00
parent d33d25674f
commit dd4a4dc23b
4 changed files with 49 additions and 38 deletions

View File

@ -84,17 +84,13 @@ void i8080::daa() {
flags.C = c; flags.C = c;
} }
const uint8_t partab[] PROGMEM = { uint8_t parity(uint8_t r) {
0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, uint8_t c = 0;
0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, while (r) {
0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, r &= (r-1);
0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, c++;
}; }
return !(c & 1);
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);
} }
void i8080::_op(uint8_t op) { void i8080::_op(uint8_t op) {

View File

@ -5,7 +5,7 @@
#undef PC #undef PC
#undef SP #undef SP
uint8_t parity_tbl(uint8_t); uint8_t parity(uint8_t);
class i8080: public CPU { class i8080: public CPU {
public: public:
@ -76,7 +76,7 @@ private:
inline void _szp(uint8_t r) { inline void _szp(uint8_t r) {
flags.S = ((r & 0x80) != 0); flags.S = ((r & 0x80) != 0);
flags.Z = (r == 0); flags.Z = (r == 0);
flags.P = parity_tbl(r); flags.P = parity(r);
} }
inline void _szhp(uint8_t b, uint8_t r) { inline void _szhp(uint8_t b, uint8_t r) {

57
z80.cpp
View File

@ -136,7 +136,7 @@ void z80::daa() {
else else
_add(a); _add(a);
flags.C = c; flags.C = c;
flags.P = parity_table(A); flags.P = parity(A);
} }
void z80::_step_idx(EXT_OP f) { void z80::_step_idx(EXT_OP f) {
@ -603,6 +603,7 @@ void z80::ed() {
SP = _rwPC(); SP = _rwPC();
break; break;
case 0xa0: case 0xa0:
// ldi
b = _rb(HL); b = _rb(HL);
BC--; BC--;
_sb(DE, b); _sb(DE, b);
@ -617,6 +618,7 @@ void z80::ed() {
flags.N = flags.H = 0; flags.N = flags.H = 0;
break; break;
case 0xa1: case 0xa1:
// cpi
b = _rb(HL); b = _rb(HL);
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
@ -635,6 +637,7 @@ void z80::ed() {
_memptr++; _memptr++;
break; break;
case 0xa2: case 0xa2:
// ini
_mc(IR, 1); _mc(IR, 1);
b = _inr(BC); b = _inr(BC);
_sb(HL, b); _sb(HL, b);
@ -643,10 +646,11 @@ void z80::ed() {
c = b + C + 1; c = b + C + 1;
flags.N = (b & 0x80) != 0; flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
break; break;
case 0xa3: case 0xa3:
// outi
_mc(IR, 1); _mc(IR, 1);
b = _rb(HL); b = _rb(HL);
B--; B--;
@ -655,10 +659,11 @@ void z80::ed() {
c = b + L; c = b + L;
flags.N = (b & 0x80) != 0; flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
break; break;
case 0xa8: case 0xa8:
// ldd
b = _rb(HL); b = _rb(HL);
BC--; BC--;
_sb(DE, b); _sb(DE, b);
@ -673,6 +678,7 @@ void z80::ed() {
flags.N = flags.H = 0; flags.N = flags.H = 0;
break; break;
case 0xa9: case 0xa9:
// cpd
b = _rb(HL); b = _rb(HL);
c = A - b - flags.H; c = A - b - flags.H;
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
@ -687,6 +693,7 @@ void z80::ed() {
// FIXME: flag H // FIXME: flag H
break; break;
case 0xaa: case 0xaa:
// ind
_mc(IR, 1); _mc(IR, 1);
b = _inr(BC); b = _inr(BC);
_memptr = BC-1; _memptr = BC-1;
@ -696,10 +703,11 @@ void z80::ed() {
c = b + C - 1; c = b + C - 1;
flags.N = (b & 0x80) != 0; flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
break; break;
case 0xab: case 0xab:
// outd
_mc(IR, 1); _mc(IR, 1);
b = _rb(HL); b = _rb(HL);
B--; B--;
@ -709,10 +717,11 @@ void z80::ed() {
c = b + L; c = b + L;
flags.N = (b & 0x80) != 0; flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
break; break;
case 0xb0: case 0xb0:
// ldir
b = _rb(HL); b = _rb(HL);
BC--; BC--;
_sb(DE, b); _sb(DE, b);
@ -721,6 +730,7 @@ void z80::ed() {
b += A; b += A;
flags.P = (BC != 0); flags.P = (BC != 0);
_35(b); _35(b);
flags._5 = ((b & 0x02) != 0);
flags.N = flags.H = 0; flags.N = flags.H = 0;
if (BC) { if (BC) {
_mc(DE, 1); _mc(DE, 1); _mc(DE, 1); _mc(DE, 1); _mc(DE, 1); _mc(DE, 1);
@ -732,6 +742,7 @@ void z80::ed() {
HL++; HL++;
break; break;
case 0xb1: case 0xb1:
// cpir
b = _rb(HL); b = _rb(HL);
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _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); f = (flags.C != 0);
_sub(b); _sub(b);
BC--; BC--;
b = A; b -= A;
A = c; A = c;
flags.C = f; flags.C = f;
flags.P = (BC != 0); flags.P = (BC != 0);
if (flags.H) b--; if (flags.H) b--;
_35(b); _35(b);
flags._5 = ((b & 0x02) != 0);
_memptr++; _memptr++;
if (!flags.Z) { if (!flags.Z) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
@ -755,6 +767,7 @@ void z80::ed() {
HL++; HL++;
break; break;
case 0xb2: case 0xb2:
// inir
_mc(IR, 1); _mc(IR, 1);
b = _inr(BC); b = _inr(BC);
_sb(HL, b); _sb(HL, b);
@ -762,7 +775,7 @@ void z80::ed() {
c = b + flags.C + 1; c = b + flags.C + 1;
flags.N = (c & 0x80) != 0; flags.N = (c & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
if (B) { if (B) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
@ -772,6 +785,7 @@ void z80::ed() {
HL++; HL++;
break; break;
case 0xb3: case 0xb3:
// outir
_mc(IR, 1); _mc(IR, 1);
b = _rb(HL); b = _rb(HL);
B--; B--;
@ -780,7 +794,7 @@ void z80::ed() {
c = b + L; c = b + L;
flags.N = (b & 0x80) != 0; flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
if (B) { if (B) {
_mc(BC, 1); _mc(BC, 1); _mc(BC, 1); _mc(BC, 1); _mc(BC, 1); _mc(BC, 1);
@ -789,6 +803,7 @@ void z80::ed() {
} }
break; break;
case 0xb8: case 0xb8:
// lddr
b = _rb(HL); b = _rb(HL);
BC--; BC--;
_sb(DE, b); _sb(DE, b);
@ -809,6 +824,7 @@ void z80::ed() {
HL--; HL--;
break; break;
case 0xb9: case 0xb9:
// cpdr
b = _rb(HL); b = _rb(HL);
c = A - b; c = A - b;
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
@ -829,6 +845,7 @@ void z80::ed() {
HL--; HL--;
break; break;
case 0xba: case 0xba:
// indr
_mc(IR, 1); _mc(IR, 1);
b = _inr(BC); b = _inr(BC);
_memptr = BC-1; _memptr = BC-1;
@ -837,7 +854,7 @@ void z80::ed() {
c = b + flags.C + 1; c = b + flags.C + 1;
flags.N = (c & 0x80) != 0; flags.N = (c & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
if (B) { if (B) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
@ -847,6 +864,7 @@ void z80::ed() {
HL--; HL--;
break; break;
case 0xbb: case 0xbb:
// outdr
_mc(IR, 1); _mc(IR, 1);
b = _rb(HL); b = _rb(HL);
B--; B--;
@ -856,7 +874,7 @@ void z80::ed() {
c = b + L; c = b + L;
flags.N = (b & 0x80) != 0; flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b); flags.C = flags.H = (c < b);
flags.P = parity_table((c & 0x07) ^ B); flags.P = parity((c & 0x07) ^ B);
_sz35(B); _sz35(B);
if (B) { if (B) {
_mc(BC, 1); _mc(BC, 1); _mc(BC, 1); _mc(BC, 1); _mc(BC, 1); _mc(BC, 1);
@ -867,17 +885,14 @@ void z80::ed() {
} }
} }
const uint8_t partab[] PROGMEM = { // kernighan's algorithm
0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, uint8_t z80::parity(uint8_t r) {
0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, uint8_t c = 0;
0x96, 0x69, 0x69, 0x96, 0x69, 0x96, 0x96, 0x69, while (r) {
0x69, 0x96, 0x96, 0x69, 0x96, 0x69, 0x69, 0x96, r &= (r-1);
}; c++;
}
uint8_t z80::parity_table(uint8_t r) { return !(c & 1);
uint8_t i = r / 8, b = pgm_read_byte(partab + i);
uint8_t m = (1 << (r % 8));
return m == (b & m);
} }
void z80::cb() { void z80::cb() {

8
z80.h
View File

@ -148,7 +148,7 @@ private:
int _irq_pending; int _irq_pending;
PortDevice<z80> *_ports; PortDevice<z80> *_ports;
uint8_t parity_table(uint8_t); uint8_t parity(uint8_t);
inline uint8_t _rb(Memory::address a) { inline uint8_t _rb(Memory::address a) {
#if defined(CPU_DEBUG) #if defined(CPU_DEBUG)
@ -222,7 +222,7 @@ private:
inline void _szp35(uint8_t r) { inline void _szp35(uint8_t r) {
_sz35(r); _sz35(r);
flags.P = parity_table(r); flags.P = parity(r);
} }
inline void _inc(uint8_t &b) { inline void _inc(uint8_t &b) {
@ -500,7 +500,7 @@ private:
inline void inca() { _inc(A); } inline void inca() { _inc(A); }
inline void deca() { _dec(A); } inline void deca() { _dec(A); }
inline void lda() { A = _rb(PC++); } 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 // 0x40
inline void ldbb() {} inline void ldbb() {}
@ -937,7 +937,7 @@ private:
} }
inline void _bitHL(int i) { 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); } inline void bit0b() { _bit(0, B); }