z80 updates

This commit is contained in:
Stephen Crane 2019-03-25 16:12:08 +00:00
parent cd4b280410
commit 0489c1d283
3 changed files with 429 additions and 466 deletions

7
CPU.h
View File

@ -5,11 +5,14 @@
class Stream; class Stream;
#define O(o, e) case o: e(); break; #define O(o, e) case o: e(); break
#define D(e) default: e(); break; #define A(o, e, a) case o: e(a); break
#define C(o) case o:
#define D(e) default: e(); break
class CPU: public Checkpointable { class CPU: public Checkpointable {
public: public:
virtual ~CPU() {}
virtual void run(unsigned instructions) =0; virtual void run(unsigned instructions) =0;
virtual void reset() =0; virtual void reset() =0;
virtual void raise(uint8_t level) =0; virtual void raise(uint8_t level) =0;

545
z80.cpp
View File

@ -425,463 +425,94 @@ void z80::_ddfd(uint16_t &ix, uint8_t &ixL, uint8_t &ixH, EXT_OP op) {
} }
void z80::ed() { void z80::ed() {
uint8_t b, c, f;
switch (_fetch_op()) { switch (_fetch_op()) {
case 0x40: O(0x40, inB);
B = _inr(BC); O(0x41, outB);
break; O(0x42, sbcBC);
case 0x41: O(0x43, ldPCbc);
_outr(BC, B);
break; C(0x44);
case 0x42: C(0x54);
_sbc16(BC); C(0x64);
break; C(0x74);
case 0x43: C(0x4c);
_swPC(BC); C(0x5c);
break; C(0x6c);
case 0x44: O(0x7c, neg);
case 0x54:
case 0x64: C(0x45);
case 0x74: C(0x4d);
case 0x4c: C(0x55);
case 0x5c: C(0x5d);
case 0x6c: C(0x65);
case 0x7c: C(0x6d);
b = A; C(0x75);
A = 0; O(0x7d, retn);
_sub(b);
break; C(0x46);
case 0x45: C(0x4e);
case 0x4d: C(0x66);
case 0x55: A(0x6e, im, 0);
case 0x5d: O(0x47, ldia);
case 0x65: O(0x48, inC);
case 0x6d: O(0x49, outC);
case 0x75: O(0x4a, adcBC);
case 0x7d: O(0x4b, ldbcPC);
_iff1 = _iff2; O(0x4f, ldra);
ret(); O(0x50, inD);
break; O(0x51, outD);
case 0x46: O(0x52, sbcDE);
case 0x4e: O(0x53, ldPCde);
case 0x66:
case 0x6e: C(0x56);
_im = 0; A(0x76, im, 1);
break;
case 0x47: O(0x57, ldai);
_mc(IR, 1); O(0x58, inE);
I = A; O(0x59, outE);
break; O(0x5a, adcDE);
case 0x48: O(0x5b, lddePC);
C = _inr(BC); C(0x5e);
break; A(0x7e, im, 2);
case 0x49: O(0x5f, ldar);
_outr(BC, C);
break; O(0x60, inH);
case 0x4a: O(0x61, outH);
_adc16(BC); O(0x62, sbcHL);
break; O(0x63, ldPChl);
case 0x4b: O(0x67, rrd);
BC = _rwPC(); O(0x68, inL);
break; O(0x69, outL);
case 0x4f: O(0x6a, adcHL);
_mc(IR, 1); O(0x6b, ldhlPC);
R = A; O(0x6f, rld);
break;
case 0x50: O(0x70, _inr);
D = _inr(BC); A(0x71, _outr, 0);
break; O(0x72, sbcSP);
case 0x51: O(0x73, ldPCsp);
_outr(BC, D); O(0x78, inA);
break; O(0x79, outA);
case 0x52: O(0x7a, adcSP);
_sbc16(DE); O(0x7b, ldspPC);
break;
case 0x53: O(0xa0, ldi);
_swPC(DE); O(0xa1, cpi);
break; O(0xa2, ini);
case 0x56: O(0xa3, outi);
case 0x76: O(0xa8, ldd_);
_im = 1; O(0xa9, cpd_);
break; O(0xaa, ind);
case 0x57: O(0xab, outd);
_mc(IR, 1);
A = I; O(0xb0, ldir);
_sz35(A); O(0xb1, cpir);
flags.P = _iff2; O(0xb2, inir);
flags.H = flags.N = 0; O(0xb3, outir);
break; O(0xb8, lddr);
case 0x58: O(0xb9, cpdr);
E = _inr(BC); O(0xba, indr);
break; O(0xbb, outdr);
case 0x59:
_outr(BC, E);
break;
case 0x5a:
_adc16(DE);
break;
case 0x5b:
DE = _rwPC();
break;
case 0x5e:
case 0x7e:
_im = 2;
break;
case 0x5f:
_mc(IR, 1);
A = R;
_sz35(A);
flags.P = _iff2;
flags.H = flags.N = 0;
break;
case 0x60:
H = _inr(BC);
break;
case 0x61:
_outr(BC, H);
break;
case 0x62:
_sbc16(HL);
break;
case 0x63:
_swPC(HL);
break;
case 0x67:
_memptr = HL+1;
b = _rb(HL);
_mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
_sb(HL, (A << 4) | (b >> 4));
A = (A & 0xf0) | (b & 0x0f);
_szp35(A);
flags.H = flags.N = 0;
break;
case 0x68:
L = _inr(BC);
break;
case 0x69:
_outr(BC, L);
break;
case 0x6a:
_adc16(HL);
break;
case 0x6b:
HL = _rwPC();
break;
case 0x6f:
_memptr = HL+1;
b = _rb(HL);
_mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
_sb(HL, (A & 0x0f) | (b << 4));
A = (A & 0xf0) | (b >> 4);
_szp35(A);
flags.N = flags.H = 0;
break;
case 0x70:
_inr(BC);
break;
case 0x71:
_outr(BC, 0);
break;
case 0x72:
_sbc16(SP);
break;
case 0x73:
_swPC(SP);
break;
case 0x78:
A = _inr(BC);
break;
case 0x79:
_outr(BC, A);
break;
case 0x7a:
_adc16(SP);
break;
case 0x7b:
SP = _rwPC();
break;
case 0xa0:
// ldi
b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
DE++;
HL++;
b += A;
flags.P = (BC != 0);
_35(b);
flags._5 = ((b & 0x02) != 0);
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);
c = A;
f = (flags.C != 0);
_sub(b);
HL++;
BC--;
b = A;
A = c;
if (flags.H) b--;
flags.C = f;
flags.P = (BC != 0);
_35(b);
flags._5 = ((b & 0x02) != 0);
_memptr++;
break;
case 0xa2:
// ini
_mc(IR, 1);
b = _inr(BC);
_sb(HL, b);
B--;
HL++;
c = b + C + 1;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
break;
case 0xa3:
// outi
_mc(IR, 1);
b = _rb(HL);
B--;
_outr(BC, b);
HL++;
c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
break;
case 0xa8:
// ldd
b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
DE--;
HL--;
b += A;
flags.P = (BC != 0);
_35(b);
flags._5 = ((b & 0x02) != 0);
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);
_mc(HL, 1); _mc(HL, 1);
HL--;
BC--;
flags.N = 1;
flags.P = (BC != 0);
_sz35(c);
flags._5 = ((c & 0x02) != 0);
_memptr--;
// FIXME: flag H
break;
case 0xaa:
// ind
_mc(IR, 1);
b = _inr(BC);
_memptr = BC-1;
_sb(HL, b);
B--;
HL--;
c = b + C - 1;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
break;
case 0xab:
// outd
_mc(IR, 1);
b = _rb(HL);
B--;
_outr(BC, b);
_memptr = BC-1;
HL--;
c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
break;
case 0xb0:
// ldir
b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
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);
_mc(DE, 1); _mc(DE, 1);
PC -= 2;
_memptr = PC+1;
}
DE++;
HL++;
break;
case 0xb1:
// cpir
b = _rb(HL);
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
c = A;
f = (flags.C != 0);
_sub(b);
BC--;
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);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
_memptr = PC+1;
}
HL++;
break;
case 0xb2:
// inir
_mc(IR, 1);
b = _inr(BC);
_sb(HL, b);
B--;
c = b + flags.C + 1;
flags.N = (c & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
}
HL++;
break;
case 0xb3:
// outir
_mc(IR, 1);
b = _rb(HL);
B--;
_outr(BC, b);
HL++;
c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(BC, 1); _mc(BC, 1); _mc(BC, 1);
_mc(BC, 1); _mc(BC, 1);
PC -= 2;
}
break;
case 0xb8:
// lddr
b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
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);
_mc(DE, 1); _mc(DE, 1);
PC -= 2;
_memptr = PC+1;
}
DE--;
HL--;
break;
case 0xb9:
// cpdr
b = _rb(HL);
c = A - b;
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
BC--;
flags.N = 1;
flags.P = (BC != 0);
_sz35(c);
flags._5 = ((c & 0x02) != 0);
// FIXME: flag H
_memptr--;
if (BC) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
_memptr = PC+1;
}
HL--;
break;
case 0xba:
// indr
_mc(IR, 1);
b = _inr(BC);
_memptr = BC-1;
_sb(HL, b);
B--;
c = b + flags.C + 1;
flags.N = (c & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
}
HL--;
break;
case 0xbb:
// outdr
_mc(IR, 1);
b = _rb(HL);
B--;
_outr(BC, b);
_memptr = BC-1;
HL--;
c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(BC, 1); _mc(BC, 1); _mc(BC, 1);
_mc(BC, 1); _mc(BC, 1);
PC -= 2;
}
break;
} }
} }
@ -1192,8 +823,6 @@ void z80::op(uint8_t op) {
} }
} }
#define A(o, e, a) case o: e(a); break;
void z80::fdcb(uint8_t op, uint8_t a) { void z80::fdcb(uint8_t op, uint8_t a) {
switch (op) { switch (op) {
A(0x00, rlcIYB, a); A(0x01, rlcIYC, a); A(0x00, rlcIYB, a); A(0x01, rlcIYC, a);

343
z80.h
View File

@ -745,16 +745,16 @@ private:
inline void rst20() { _mc(IR, 1); _push(PC); _memptr = PC = 0x20; } inline void rst20() { _mc(IR, 1); _push(PC); _memptr = PC = 0x20; }
// 0xe8 // 0xe8
inline uint8_t _inr(uint16_t p) { inline uint8_t _inr() {
_memptr = p+1; _memptr = BC+1;
uint8_t b = _ports->in(p, this); uint8_t b = _ports->in(BC, this);
_szp35(b); _szp35(b);
flags.N = flags.H = 0; flags.N = flags.H = 0;
return b; return b;
} }
inline void _outr(uint16_t p, uint8_t b) { inline void _outr(uint8_t b) {
_memptr = p+1; _memptr = BC+1;
_ports->out(p, b, this); _ports->out(BC, b, this);
} }
inline void retpe() { _ret(flags.P); } inline void retpe() { _ret(flags.P); }
@ -1198,6 +1198,337 @@ private:
_35(a >> 8); _35(a >> 8);
} }
// 0xED extended instructions
inline void inB() { B = _inr(); }
inline void inC() { C = _inr(); }
inline void inD() { D = _inr(); }
inline void inE() { E = _inr(); }
inline void inH() { H = _inr(); }
inline void inL() { L = _inr(); }
inline void inA() { A = _inr(); }
inline void outB() { _outr(B); }
inline void outC() { _outr(C); }
inline void outD() { _outr(D); }
inline void outE() { _outr(E); }
inline void outH() { _outr(H); }
inline void outL() { _outr(L); }
inline void outA() { _outr(A); }
inline void sbcBC() { _sbc16(BC); }
inline void sbcDE() { _sbc16(DE); }
inline void sbcHL() { _sbc16(HL); }
inline void sbcSP() { _sbc16(SP); }
inline void adcBC() { _adc16(BC); }
inline void adcDE() { _adc16(DE); }
inline void adcHL() { _adc16(HL); }
inline void adcSP() { _adc16(SP); }
inline void ldPCbc() { _swPC(BC); }
inline void ldPCde() { _swPC(DE); }
inline void ldPCsp() { _swPC(SP); }
inline void ldbcPC() { BC = _rwPC(); }
inline void lddePC() { DE = _rwPC(); }
inline void ldspPC() { SP = _rwPC(); }
inline void neg() { uint8_t b = A; A = 0; _sub(b); }
inline void retn() { _iff1 = _iff2; ret(); }
inline void ldia() { _mc(IR, 1); I = A; }
inline void ldra() { _mc(IR, 1); R = A; }
inline void ldai() {
_mc(IR, 1);
A = I;
_sz35(A);
flags.P = _iff2;
flags.H = flags.N = 0;
}
inline void ldar() {
_mc(IR, 1);
A = R;
_sz35(A);
flags.P = _iff2;
flags.H = flags.N = 0;
}
inline void rrd() {
_memptr = HL+1;
uint8_t b = _rb(HL);
_mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
_sb(HL, (A << 4) | (b >> 4));
A = (A & 0xf0) | (b & 0x0f);
_szp35(A);
flags.H = flags.N = 0;
}
inline void rld() {
_memptr = HL+1;
uint8_t b = _rb(HL);
_mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
_sb(HL, (A & 0x0f) | (b << 4));
A = (A & 0xf0) | (b >> 4);
_szp35(A);
flags.N = flags.H = 0;
}
inline void ldi() {
uint8_t b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
DE++;
HL++;
b += A;
flags.P = (BC != 0);
_35(b);
flags._5 = ((b & 0x02) != 0);
flags.N = flags.H = 0;
}
inline void cpi() {
uint8_t b = _rb(HL);
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
uint8_t c = A;
uint8_t f = (flags.C != 0);
_sub(b);
HL++;
BC--;
b = A;
A = c;
if (flags.H) b--;
flags.C = f;
flags.P = (BC != 0);
_35(b);
flags._5 = ((b & 0x02) != 0);
_memptr++;
}
inline void ini() {
_mc(IR, 1);
uint8_t b = _inr();
_sb(HL, b);
B--;
HL++;
uint8_t c = b + C + 1;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
}
inline void outi() {
_mc(IR, 1);
uint8_t b = _rb(HL);
B--;
_outr(b);
HL++;
uint8_t c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
}
inline void ldd_() {
uint8_t b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
DE--;
HL--;
b += A;
flags.P = (BC != 0);
_35(b);
flags._5 = ((b & 0x02) != 0);
flags.N = flags.H = 0;
}
inline void cpd_() {
uint8_t b = _rb(HL);
uint8_t c = A - b - flags.H;
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
HL--;
BC--;
flags.N = 1;
flags.P = (BC != 0);
_sz35(c);
flags._5 = ((c & 0x02) != 0);
_memptr--;
// FIXME: flag H
}
inline void ind() {
_mc(IR, 1);
uint8_t b = _inr();
_memptr = BC-1;
_sb(HL, b);
B--;
HL--;
uint8_t c = b + C - 1;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
}
inline void outd() {
_mc(IR, 1);
uint8_t b = _rb(HL);
B--;
_outr(b);
_memptr = BC-1;
HL--;
uint8_t c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
}
inline void ldir() {
uint8_t b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
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);
_mc(DE, 1); _mc(DE, 1);
PC -= 2;
_memptr = PC+1;
}
DE++;
HL++;
}
inline void cpir() {
uint8_t b = _rb(HL);
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
uint8_t c = A;
uint8_t f = (flags.C != 0);
_sub(b);
BC--;
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);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
_memptr = PC+1;
}
HL++;
}
inline void inir() {
_mc(IR, 1);
uint8_t b = _inr();
_sb(HL, b);
B--;
uint8_t c = b + flags.C + 1;
flags.N = (c & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
}
HL++;
}
inline void outir() {
_mc(IR, 1);
uint8_t b = _rb(HL);
B--;
_outr(b);
HL++;
uint8_t c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(BC, 1); _mc(BC, 1); _mc(BC, 1);
_mc(BC, 1); _mc(BC, 1);
PC -= 2;
}
}
inline void lddr() {
uint8_t b = _rb(HL);
BC--;
_sb(DE, b);
_mc(DE, 1);
_mc(DE, 1);
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);
_mc(DE, 1); _mc(DE, 1);
PC -= 2;
_memptr = PC+1;
}
DE--;
HL--;
}
inline void cpdr() {
uint8_t b = _rb(HL);
uint8_t c = A - b;
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
BC--;
flags.N = 1;
flags.P = (BC != 0);
_sz35(c);
flags._5 = ((c & 0x02) != 0);
// FIXME: flag H
_memptr--;
if (BC) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
_memptr = PC+1;
}
HL--;
}
inline void indr() {
_mc(IR, 1);
uint8_t b = _inr();
_memptr = BC-1;
_sb(HL, b);
B--;
uint8_t c = b + flags.C + 1;
flags.N = (c & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(HL, 1); _mc(HL, 1); _mc(HL, 1);
_mc(HL, 1); _mc(HL, 1);
PC -= 2;
}
HL--;
}
inline void outdr() {
_mc(IR, 1);
uint8_t b = _rb(HL);
B--;
_outr(b);
_memptr = BC-1;
HL--;
uint8_t c = b + L;
flags.N = (b & 0x80) != 0;
flags.C = flags.H = (c < b);
flags.P = parity((c & 0x07) ^ B);
_sz35(B);
if (B) {
_mc(BC, 1); _mc(BC, 1); _mc(BC, 1);
_mc(BC, 1); _mc(BC, 1);
PC -= 2;
}
}
// 0xDDCB extended instructions // 0xDDCB extended instructions
inline uint16_t _rbIX(uint8_t &b, uint8_t o) { inline uint16_t _rbIX(uint8_t &b, uint8_t o) {