diff --git a/CPU.h b/CPU.h index 7bb5035..794a913 100644 --- a/CPU.h +++ b/CPU.h @@ -1,32 +1,25 @@ #ifndef __CPU_H__ #define __CPU_H__ -#ifndef _SETJMP_H -#include -#endif - #undef PC class CPU: public Checkpointable { public: virtual void run(unsigned instructions) =0; - virtual void reset () =0; - virtual void raise (int level) =0; - virtual char *status () =0; - - typedef void (*statfn) (const char *, ...); + virtual void reset() =0; + virtual void raise(int level) =0; + virtual char *status(char *buf, size_t n) =0; virtual void checkpoint(Stream &s) = 0; virtual void restore(Stream &s) = 0; - void debug() { _debug = !_debug; } + inline void debug() { _debug = !_debug; } + inline bool halted() { return _halted; } protected: - CPU (Memory &mem, jmp_buf &e, statfn s): _mem(mem), _err(e), _status(s), _debug(false) {} + CPU(Memory &mem): _mem(mem), _debug(false), _halted(false) {} Memory &_mem; Memory::address PC; - jmp_buf &_err; - statfn _status; - bool _debug; + bool _debug, _halted; }; #endif diff --git a/i8080.cpp b/i8080.cpp index 1477228..af58097 100644 --- a/i8080.cpp +++ b/i8080.cpp @@ -5,29 +5,14 @@ #include "ports.h" #include "i8080.h" -#define CPU_STATE_FMT "%04x %02x %02x %04x %04x %04x %04x %d%d%d%d%d%d%d%d\r",\ - PC, op, A, BC, DE, HL, SP, flags.S, flags.Z,\ - flags.I, flags.H, flags._, flags.P, flags.__, flags.C - -void i8080::step() { - byte op = _mem[PC]; -#if defined(CPU_DEBUG) - if (_debug) - _status(CPU_STATE_FMT); -#endif - PC++; - (this->*_ops[op])(); -} - void i8080::run(unsigned clocks) { -#if defined(CPU_DEBUG) - if (_debug) { - step(); - return; + while (clocks--) { + byte op = _mem[PC]; + PC++; + (this->*_ops[op])(); + if (_halted) + break; } -#endif - while (clocks--) - step(); } void i8080::reset() { @@ -35,6 +20,7 @@ void i8080::reset() { _sr(0); BC = DE = HL = PC = SP = 0; _irq_pending = 0; + _halted = false; } void i8080::raise(int level) { @@ -53,10 +39,12 @@ void i8080::ei() { raise(_irq_pending); } -char *i8080::status() { - static char buf[128]; +char *i8080::status(char *buf, size_t n) { byte op = _mem[PC]; - sprintf(buf, "_pc_ op aa _bc_ _de_ _hl_ _sp_ szih_p_c\r" CPU_STATE_FMT); + snprintf(buf, n, "_pc_ op aa _bc_ _de_ _hl_ _sp_ szih_p_c\r" + "%04x %02x %02x %04x %04x %04x %04x %d%d%d%d%d%d%d%d\r", + PC, op, A, BC, DE, HL, SP, flags.S, flags.Z, flags.I, flags.H, + flags._, flags.P, flags.__, flags.C); return buf; } @@ -94,11 +82,6 @@ void i8080::daa() { flags.C = c; } -void i8080::hlt() { - _status("CPU halted at %04x\r%s", (PC-1), status()); - longjmp(_err, 1); -} - int i8080::parity_table[] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, @@ -118,7 +101,7 @@ int i8080::parity_table[] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, }; -i8080::i8080(Memory &m, jmp_buf &jb, CPU::statfn s, PortDevice &d): CPU(m, jb, s) +i8080::i8080(Memory &m, PortDevice &d): CPU(m) { _ports = &d; diff --git a/i8080.h b/i8080.h index 74dc8d8..c84bdce 100644 --- a/i8080.h +++ b/i8080.h @@ -6,12 +6,12 @@ class i8080: public CPU { public: - i8080(Memory &, jmp_buf &, CPU::statfn, PortDevice &); + i8080(Memory &, PortDevice &); void run(unsigned); void reset(); void raise(int); - char *status(); + char *status(char *buf, size_t n); void checkpoint(Stream &); void restore(Stream &); @@ -29,8 +29,6 @@ public: inline byte sr() { return SR; } private: - inline void step(); - byte A; union { struct { byte C, B; }; @@ -232,7 +230,7 @@ private: void movme() { _mem[HL] = E; } void movmh() { _mem[HL] = H; } void movml() { _mem[HL] = L; } - void hlt(); + void hlt() { _halted = true; PC--; } void movma() { _mem[HL] = A; } void movab() { A = B; } diff --git a/r6502.cpp b/r6502.cpp index 0a76952..ae0de96 100644 --- a/r6502.cpp +++ b/r6502.cpp @@ -5,31 +5,14 @@ #include "CPU.h" #include "r6502.h" -#define CPU_STATE_FMT "%02x %02x %02x %02x %d%d%d%d%d%d%d%d %04x\r",\ - A,X,Y,S,P.bits.N,P.bits.V,P.bits._,P.bits.B,\ - P.bits.D,P.bits.I,P.bits.Z,P.bits.C,PC - -inline void r6502::step() { - byte op = _mem[PC]; -#ifdef CPU_DEBUG - if (_debug) { - flags(); - _status(CPU_STATE_FMT); - } -#endif - PC++; - (this->*_ops[op])(); -} - void r6502::run(unsigned clocks) { -#ifdef CPU_DEBUG - if (_debug) { - step(); - return; + while (clocks--) { + byte op = _mem[PC]; + PC++; + (this->*_ops[op])(); + if (_halted) + break; } -#endif - while (clocks--) - step(); } byte r6502::flags() { @@ -38,13 +21,16 @@ byte r6502::flags() { P.bits.Z = !Z; P.bits.C = C; P.bits._ = 1; - return P.value; + return P.flags; } -char *r6502::status () { - static char buf[128]; +char *r6502::status(char *buf, size_t n) { flags(); - sprintf (buf, "aa xx yy sp nv_bdizc _pc_\r" CPU_STATE_FMT); + snprintf(buf, n, "aa xx yy sp nv_bdizc _pc_\r" + "%02x %02x %02x %02x %d%d%d%d%d%d%d%d %04x\r", + A, X, Y, S, P.bits.N, P.bits.V, P.bits._, P.bits.B, + P.bits.D, P.bits.I, P.bits.Z, P.bits.C, PC); + return buf; } @@ -52,18 +38,18 @@ void r6502::checkpoint(Stream &s) { s.write(PC / 0xff); s.write(PC % 0xff); - s.write(S); - s.write(A); - s.write(X); - s.write(Y); - s.write(N); - s.write(V); - s.write(B); - s.write(D); - s.write(I); - s.write(Z); - s.write(C); - s.write(P.value); + s.write(S); + s.write(A); + s.write(X); + s.write(Y); + s.write(N); + s.write(V); + s.write(B); + s.write(D); + s.write(I); + s.write(Z); + s.write(C); + s.write(P.flags); } void r6502::restore(Stream &s) @@ -81,83 +67,83 @@ void r6502::restore(Stream &s) I = s.read(); Z = s.read(); C = s.read(); - P.value = s.read(); + P.flags = s.read(); } -void r6502::raise (int level) { +void r6502::raise(int level) { if (level < 0) - nmi (); + nmi(); else if (!P.bits.I) - irq (); + irq(); else _irq = true; } -void r6502::irq () { - pusha (PC); +void r6502::irq() { + pusha(PC); P.bits.B = 0; - pushb (flags ()); + pushb(flags()); P.bits.B = 1; P.bits.I = 1; - PC = vector (ibvec); + PC = vector(ibvec); _irq = false; } -void r6502::brk () { +void r6502::brk() { if (!P.bits.I) { - pusha (PC); + pusha(PC); P.bits.B = 1; - php (); + php(); P.bits.I = 1; - PC = vector (ibvec); + PC = vector(ibvec); } P.bits.B = 1; P.bits._ = 1; } -void r6502::rti () { - plp (); - PC = popa (); +void r6502::rti() { + plp(); + PC = popa(); } -void r6502::cli () { +void r6502::cli() { P.bits.I = 0; if (_irq) irq(); } -void r6502::nmi () { - pusha (PC); - php (); +void r6502::nmi() { + pusha(PC); + php(); P.bits.I = 1; - PC = vector (nmivec); + PC = vector(nmivec); } // php and plp are complicated by the representation // of the processor state for efficient normal operation -void r6502::php () { +void r6502::php() { P.bits.B = 1; - pushb (flags ()); + pushb(flags()); } -void r6502::plp () { - P.value = popb (); +void r6502::plp() { + P.flags = popb(); N = P.bits.N? 0x80: 0; V = P.bits.V; Z = !P.bits.Z; C = P.bits.C; } -void r6502::rts () { - PC = popa ()+1; +void r6502::rts() { + PC = popa()+1; } -void r6502::jsr () { - pusha (PC+1); - PC = vector (PC); +void r6502::jsr() { + pusha(PC+1); + PC = vector(PC); } -void r6502::_adc (byte d) { +void r6502::_adc(byte d) { if (P.bits.D) { int r = _fromBCD[A] + _fromBCD[d] + C; C = (r > 99); @@ -174,7 +160,7 @@ void r6502::_adc (byte d) { Z = A; } -void r6502::sbcd (byte d) { +void r6502::sbcd(byte d) { int r = _fromBCD[A] - _fromBCD[d] - !C; C = (r >= 0); if (r < 0) r += 100; @@ -185,14 +171,14 @@ void r6502::sbcd (byte d) { } void r6502::ill() { - _status("Illegal instruction at %04x!\r\n%s", (PC-1), status()); - longjmp(_err, 1); + --PC; + _halted = true; } void r6502::reset() { - _debug = false; - P.value = 0; + _debug = _halted = false; + P.flags = 0; P.bits._ = 1; P.bits.B = 1; _irq = false; @@ -200,13 +186,13 @@ void r6502::reset() PC = vector(resvec); } -r6502::r6502 (Memory &m, jmp_buf &e, CPU::statfn s): CPU (m,e,s) { +r6502::r6502(Memory &m): CPU(m) { for (int i=0; i < 256; i++) { _fromBCD[i] = ((i >> 4) & 0x0f)*10 + (i & 0x0f); _toBCD[i] = (((i % 100) / 10) << 4) | (i % 10); } - + OP *p = _ops; *p++=&r6502::brk; *p++=&r6502::ora_ix; *p++=&r6502::ill; *p++=&r6502::ill; *p++=&r6502::nop2; *p++=&r6502::ora_z; *p++=&r6502::asl_z; *p++=&r6502::ill; diff --git a/r6502.h b/r6502.h index a0aa1cd..8e2c617 100644 --- a/r6502.h +++ b/r6502.h @@ -9,11 +9,11 @@ public: void raise(int); void reset(); void run(unsigned); - char *status(); + char *status(char *buf, size_t n); void checkpoint(Stream &); void restore(Stream &); - r6502 (Memory &, jmp_buf &, CPU::statfn); + r6502(Memory &); private: /* registers */ byte S, A, X, Y; @@ -29,33 +29,32 @@ private: unsigned V:1; unsigned N:1; } bits; - byte value; + byte flags; } P; byte _toBCD[256], _fromBCD[256]; // BCD maps bool _irq; // interrupt pending? - void step(); void irq(); void nmi(); byte flags(); /* stack */ - inline void pusha (Memory::address ret) { + inline void pusha(Memory::address ret) { _mem[0x0100+S--] = ret >> 8; _mem[0x0100+S--] = ret & 0xff; } - inline void pushb (byte b) { + inline void pushb(byte b) { _mem[0x0100+S--] = b; } - inline byte popb () { + inline byte popb() { return _mem[++S+0x0100]; } - inline Memory::address popa () { - byte b = popb (); - return ((popb () << 8) | b); + inline Memory::address popa() { + byte b = popb(); + return (popb() << 8) | b; } static const Memory::address nmivec = 0xfffa; @@ -67,63 +66,63 @@ private: } /* operators */ - inline void _cmp (byte a) { Z=N=A-a; C=(A>=a); } - inline void _cpx (byte a) { Z=N=X-a; C=(X>=a); } - inline void _cpy (byte a) { Z=N=Y-a; C=(Y>=a); } - inline void _and (byte a) { Z=N=A&=a; } - inline void _eor (byte a) { Z=N=A^=a; } - inline void _ora (byte a) { Z=N=A|=a; } - inline void _lda (byte a) { Z=N=A=a; } - inline void _ldx (byte a) { Z=N=X=a; } - inline void _ldy (byte a) { Z=N=Y=a; } + inline void _cmp(byte a) { Z=N=A-a; C=(A>=a); } + inline void _cpx(byte a) { Z=N=X-a; C=(X>=a); } + inline void _cpy(byte a) { Z=N=Y-a; C=(Y>=a); } + inline void _and(byte a) { Z=N=A&=a; } + inline void _eor(byte a) { Z=N=A^=a; } + inline void _ora(byte a) { Z=N=A|=a; } + inline void _lda(byte a) { Z=N=A=a; } + inline void _ldx(byte a) { Z=N=X=a; } + inline void _ldy(byte a) { Z=N=Y=a; } /* modes */ - inline Memory::address _a () { + inline Memory::address _a() { Memory::address a = _mem[PC++]; return a | (_mem[PC++] << 8); } - inline Memory::address _ax () { return _a()+X; } - inline Memory::address _ay () { return _a()+Y; } - inline Memory::address _z () { return _mem[PC++]; } - inline Memory::address _zx () { return (_z()+X) & 0xff; } - inline Memory::address _zy () { return (_z()+Y) & 0xff; } - inline Memory::address _i (Memory::address a) { + inline Memory::address _ax() { return _a()+X; } + inline Memory::address _ay() { return _a()+Y; } + inline Memory::address _z() { return _mem[PC++]; } + inline Memory::address _zx() { return (_z()+X) & 0xff; } + inline Memory::address _zy() { return (_z()+Y) & 0xff; } + inline Memory::address _i(Memory::address a) { return (_mem[a+1]<<8)|_mem[a]; } - inline Memory::address _ix () { return _i(_zx()); } - inline Memory::address _iy () { return _i(_mem[PC++])+Y; } + inline Memory::address _ix() { return _i(_zx()); } + inline Memory::address _iy() { return _i(_mem[PC++])+Y; } - void _adc (byte a); - void _sbc (byte a) { if (P.bits.D) sbcd(a); else _adc(~a); } - void sbcd (byte a); + void _adc(byte a); + void _sbc(byte a) { if (P.bits.D) sbcd(a); else _adc(~a); } + void sbcd(byte a); - inline byte __ror (byte b) { + inline byte __ror(byte b) { N=b>>1; if (C) N|=0x80; C=b&1; return Z=N; } - inline void _ror (Memory::address a) { + inline void _ror(Memory::address a) { _mem[a] = __ror(_mem[a]); } - inline byte __rol (byte b) { + inline byte __rol(byte b) { N=b<<1; if (C) N|=1; C=(b&0x80)!=0; return Z=N; } - inline void _rol (Memory::address a) { + inline void _rol(Memory::address a) { _mem[a] = __rol(_mem[a]); } - inline byte __asl (byte b) { C=(b&0x80)!=0; return Z=N=b<<1; } - inline void _asl (Memory::address a) { + inline byte __asl(byte b) { C=(b&0x80)!=0; return Z=N=b<<1; } + inline void _asl(Memory::address a) { _mem[a] = __asl(_mem[a]); } - inline byte __lsr (byte b) { C=b&1; Z=b>>1; N=0; return Z; } - inline void _lsr (Memory::address a) { + inline byte __lsr(byte b) { C=b&1; Z=b>>1; N=0; return Z; } + inline void _lsr(Memory::address a) { _mem[a] = __lsr(_mem[a]); } - inline void _inc (Memory::address a) { + inline void _inc(Memory::address a) { Z=N=1+_mem[a]; _mem[a]=Z; } - inline void _dec (Memory::address a) { + inline void _dec(Memory::address a) { Z=N=_mem[a]-1; _mem[a]=Z; } - inline void _bit (byte z) { V=((z & 0x40)!=0); N=(z & 0x80); Z=(A & z); } + inline void _bit(byte z) { V=((z & 0x40)!=0); N=(z & 0x80); Z=(A & z); } inline void _bra() { byte b = _mem[PC]; PC += b; @@ -134,180 +133,180 @@ private: typedef void (r6502::*OP)(); OP _ops[256]; /* operations */ - void brk (); - void ora_ix () { _ora (_mem[_ix()]); } - void ill (); - void nop2 () { PC++; } - void ora_z () { _ora (_mem[_z()]); } - void asl_z () { _asl (_z()); } - void php (); - void ora_ () { _ora (_mem[PC++]); } - void asl () { C=(A&0x80)!=0; Z=N=A<<=1; } - void nop3 () { PC+=2; } - void ora_a () { _ora (_mem[_a()]); } - void asl_a () { _asl (_a()); } + void brk(); + void ora_ix() { _ora(_mem[_ix()]); } + void ill(); + void nop2() { PC++; } + void ora_z() { _ora(_mem[_z()]); } + void asl_z() { _asl(_z()); } + void php(); + void ora_() { _ora(_mem[PC++]); } + void asl() { C=(A&0x80)!=0; Z=N=A<<=1; } + void nop3() { PC+=2; } + void ora_a() { _ora(_mem[_a()]); } + void asl_a() { _asl(_a()); } // 10 - void bpl () { if (!(N & 0x80)) _bra(); PC++; } - void ora_iy () { _ora (_mem[_iy()]); } - void ora_zx () { _ora (_mem[_zx()]); } - void asl_zx () { _asl (_zx()); } - void clc () { C=0; } - void ora_ay () { _ora (_mem[_ay()]); } - void nop () { } - void ora_ax () { _ora (_mem[_ax()]); } - void asl_ax () { _asl (_ax()); } + void bpl() { if (!(N & 0x80)) _bra(); PC++; } + void ora_iy() { _ora(_mem[_iy()]); } + void ora_zx() { _ora(_mem[_zx()]); } + void asl_zx() { _asl(_zx()); } + void clc() { C=0; } + void ora_ay() { _ora(_mem[_ay()]); } + void nop() {} + void ora_ax() { _ora(_mem[_ax()]); } + void asl_ax() { _asl(_ax()); } // 20 - void jsr (); - void and_ix () { _and (_mem[_ix()]); } - void bit_z () { _bit (_mem[_z()]); } - void and_z () { _and (_mem[_z()]); } - void rol_z () { _rol (_z()); } - void plp (); - void and_ () { _and (_mem[PC++]); } - void rol () { A=__rol (A); } - void bit_a () { _bit (_mem[_a()]); } - void and_a () { _and (_mem[_a()]); } - void rol_a () { _rol (_a()); } + void jsr(); + void and_ix() { _and(_mem[_ix()]); } + void bit_z() { _bit(_mem[_z()]); } + void and_z() { _and(_mem[_z()]); } + void rol_z() { _rol(_z()); } + void plp(); + void and_() { _and(_mem[PC++]); } + void rol() { A=__rol(A); } + void bit_a() { _bit(_mem[_a()]); } + void and_a() { _and(_mem[_a()]); } + void rol_a() { _rol(_a()); } // 30 - void bmi () { if (N & 0x80) _bra(); PC++; } - void and_iy () { _and (_mem[_iy()]); } - void and_zx () { _and (_mem[_zx()]); } - void rol_zx () { _rol (_zx()); } - void sec () { C=1; } - void and_ay () { _and (_mem[_ay()]); } - void and_ax () { _and (_mem[_ax()]); } - void rol_ax () { _rol (_ax()); } + void bmi() { if (N & 0x80) _bra(); PC++; } + void and_iy() { _and(_mem[_iy()]); } + void and_zx() { _and(_mem[_zx()]); } + void rol_zx() { _rol(_zx()); } + void sec() { C=1; } + void and_ay() { _and(_mem[_ay()]); } + void and_ax() { _and(_mem[_ax()]); } + void rol_ax() { _rol(_ax()); } // 40 - void rti (); - void eor_ix () { _eor (_mem[_ix()]); } - void eor_z () { _eor (_mem[_z()]); } - void lsr_z () { _lsr (_z()); } - void pha () { pushb (A); } - void eor_ () { _eor (_mem[PC++]); } - void lsr_ () { A=__lsr(A); } - void jmp () { PC = _a (); } - void eor_a () { _eor (_mem[_a()]); } - void lsr_a () { _lsr (_a()); } + void rti(); + void eor_ix() { _eor(_mem[_ix()]); } + void eor_z() { _eor(_mem[_z()]); } + void lsr_z() { _lsr(_z()); } + void pha() { pushb(A); } + void eor_() { _eor(_mem[PC++]); } + void lsr_() { A=__lsr(A); } + void jmp() { PC = _a(); } + void eor_a() { _eor(_mem[_a()]); } + void lsr_a() { _lsr(_a()); } // 50 - void bvc () { if (!V) _bra(); PC++; } - void eor_iy () { _eor (_mem[_iy()]); } - void eor_zx () { _eor (_mem[_zx()]); } - void lsr_zx () { _lsr (_zx()); } - void cli (); - void eor_ay () { _eor (_mem[_ay()]); } - void eor_ax () { _eor (_mem[_ax()]); } - void lsr_ax () { _lsr (_ax()); } + void bvc() { if (!V) _bra(); PC++; } + void eor_iy() { _eor(_mem[_iy()]); } + void eor_zx() { _eor(_mem[_zx()]); } + void lsr_zx() { _lsr(_zx()); } + void cli(); + void eor_ay() { _eor(_mem[_ay()]); } + void eor_ax() { _eor(_mem[_ax()]); } + void lsr_ax() { _lsr(_ax()); } // 60 - void rts (); - void adc_ix () { _adc (_mem[_ix()]); } - void adc_z () { _adc (_mem[_z()]); } - void ror_z () { _ror (_z()); } - void pla () { Z=N=A=popb (); } - void adc_ () { _adc (_mem[PC++]); } - void ror_ () { A=__ror (A); } - void jmp_i () { PC = _i(_a()); } - void adc_a () { _adc (_mem[_a()]); } - void ror_a () { _ror (_a()); } + void rts(); + void adc_ix() { _adc(_mem[_ix()]); } + void adc_z() { _adc(_mem[_z()]); } + void ror_z() { _ror(_z()); } + void pla() { Z=N=A=popb(); } + void adc_() { _adc(_mem[PC++]); } + void ror_() { A=__ror(A); } + void jmp_i() { PC = _i(_a()); } + void adc_a() { _adc(_mem[_a()]); } + void ror_a() { _ror(_a()); } // 70 - void bvs () { if (V) _bra(); PC++; } - void adc_iy () { _adc (_mem[_iy()]); } - void adc_zx () { _adc (_mem[_zx()]); } - void ror_zx () { _ror (_zx ()); } - void sei () { P.bits.I = 1; } - void adc_ay () { _adc (_mem[_ay()]); } - void adc_ax () { _adc (_mem[_ax()]); } - void ror_ax () { _ror (_ax ()); } + void bvs() { if (V) _bra(); PC++; } + void adc_iy() { _adc(_mem[_iy()]); } + void adc_zx() { _adc(_mem[_zx()]); } + void ror_zx() { _ror(_zx()); } + void sei() { P.bits.I = 1; } + void adc_ay() { _adc(_mem[_ay()]); } + void adc_ax() { _adc(_mem[_ax()]); } + void ror_ax() { _ror(_ax()); } // 80 - void sta_ix () { _mem[_ix()] = A; } - void sty_z () { _mem[_z()] = Y; } - void sta_z () { _mem[_z()] = A; } - void stx_z () { _mem[_z()] = X; } - void dey () { Z=N=--Y; } - void txa () { Z=N=A=X; } - void sty_a () { _mem[_a()] = Y; } - void sta_a () { _mem[_a()] = A; } - void stx_a () { _mem[_a()] = X; } + void sta_ix() { _mem[_ix()] = A; } + void sty_z() { _mem[_z()] = Y; } + void sta_z() { _mem[_z()] = A; } + void stx_z() { _mem[_z()] = X; } + void dey() { Z=N=--Y; } + void txa() { Z=N=A=X; } + void sty_a() { _mem[_a()] = Y; } + void sta_a() { _mem[_a()] = A; } + void stx_a() { _mem[_a()] = X; } // 90 - void bcc () { if (!C) _bra(); PC++; } - void sta_iy () { _mem[_iy()] = A; } - void sty_zx () { _mem[_zx()] = Y; } - void sta_zx () { _mem[_zx()] = A; } - void stx_zy () { _mem[_zy()] = X; } - void tya () { Z=N=A=Y; } - void sta_ay () { _mem[_ay()] = A; } - void txs () { S=X; } - void sta_ax () { _mem[_ax()] = A; } + void bcc() { if (!C) _bra(); PC++; } + void sta_iy() { _mem[_iy()] = A; } + void sty_zx() { _mem[_zx()] = Y; } + void sta_zx() { _mem[_zx()] = A; } + void stx_zy() { _mem[_zy()] = X; } + void tya() { Z=N=A=Y; } + void sta_ay() { _mem[_ay()] = A; } + void txs() { S=X; } + void sta_ax() { _mem[_ax()] = A; } // a0 - void ldy_ () { _ldy (_mem[PC++]); } - void lda_ix () { _lda (_mem[_ix()]); } - void ldx_ () { _ldx (_mem[PC++]); } - void lax_ix () { lda_ix (); X=A; } - void ldy_z () { _ldy (_mem[_z()]); } - void lda_z () { _lda (_mem[_z()]); } - void ldx_z () { _ldx (_mem[_z()]); } - void lax_z () { lda_z (); X=A; } - void tay () { Z=N=Y=A; } - void lda_ () { _lda (_mem[PC++]); } - void tax () { Z=N=X=A; } - void ldy_a () { _ldy (_mem[_a()]); } - void lda_a () { _lda (_mem[_a()]); } - void ldx_a () { _ldx (_mem[_a()]); } - void lax_a () { lda_a (); X=A; } + void ldy_() { _ldy(_mem[PC++]); } + void lda_ix() { _lda(_mem[_ix()]); } + void ldx_() { _ldx(_mem[PC++]); } + void lax_ix() { lda_ix(); X=A; } + void ldy_z() { _ldy(_mem[_z()]); } + void lda_z() { _lda(_mem[_z()]); } + void ldx_z() { _ldx(_mem[_z()]); } + void lax_z() { lda_z(); X=A; } + void tay() { Z=N=Y=A; } + void lda_() { _lda(_mem[PC++]); } + void tax() { Z=N=X=A; } + void ldy_a() { _ldy(_mem[_a()]); } + void lda_a() { _lda(_mem[_a()]); } + void ldx_a() { _ldx(_mem[_a()]); } + void lax_a() { lda_a(); X=A; } // b0 - void bcs () { if (C) _bra(); PC++; } - void lda_iy () { _lda (_mem[_iy()]); } - void lax_iy () { lda_iy (); X=A; } - void ldy_zx () { _ldy (_mem[_zx()]); } - void lda_zx () { _lda (_mem[_zx()]); } - void ldx_zy () { _ldx (_mem[_zy()]); } - void lax_zy () { ldx_zy (); A=X; } - void clv () { V=0; } - void lda_ay () { _lda (_mem[_ay()]); } - void tsx () { Z=N=X=S; } - void ldy_ax () { _ldy (_mem[_ax()]); } - void lda_ax () { _lda (_mem[_ax()]); } - void ldx_ay () { _ldx (_mem[_ay()]); } - void lax_ay () { ldx_ay (); A=X; } + void bcs() { if (C) _bra(); PC++; } + void lda_iy() { _lda(_mem[_iy()]); } + void lax_iy() { lda_iy(); X=A; } + void ldy_zx() { _ldy(_mem[_zx()]); } + void lda_zx() { _lda(_mem[_zx()]); } + void ldx_zy() { _ldx(_mem[_zy()]); } + void lax_zy() { ldx_zy(); A=X; } + void clv() { V=0; } + void lda_ay() { _lda(_mem[_ay()]); } + void tsx() { Z=N=X=S; } + void ldy_ax() { _ldy(_mem[_ax()]); } + void lda_ax() { _lda(_mem[_ax()]); } + void ldx_ay() { _ldx(_mem[_ay()]); } + void lax_ay() { ldx_ay(); A=X; } // c0 - void cpy_ () { _cpy (_mem[PC++]); } - void cmp_ix () { _cmp (_mem[_ix()]); } - void cpy_z () { _cpy (_mem[_z()]); } - void cmp_z () { _cmp (_mem[_z()]); } - void dec_z () { _dec (_z()); } - void iny () { Z=N=++Y; } - void cmp_ () { _cmp (_mem[PC++]); } - void dex () { Z=N=--X; } - void cpy_a () { _cpy (_mem[_a()]); } - void cmp_a () { _cmp (_mem[_a()]); } - void dec_a () { _dec (_a()); } + void cpy_() { _cpy(_mem[PC++]); } + void cmp_ix() { _cmp(_mem[_ix()]); } + void cpy_z() { _cpy(_mem[_z()]); } + void cmp_z() { _cmp(_mem[_z()]); } + void dec_z() { _dec(_z()); } + void iny() { Z=N=++Y; } + void cmp_() { _cmp(_mem[PC++]); } + void dex() { Z=N=--X; } + void cpy_a() { _cpy(_mem[_a()]); } + void cmp_a() { _cmp(_mem[_a()]); } + void dec_a() { _dec(_a()); } // d0 - void bne () { if (Z) _bra(); PC++; } - void cmp_iy () { _cmp (_mem[_iy()]); } - void cmp_zx () { _cmp (_mem[_zx()]); } - void dec_zx () { _dec (_zx()); } - void cld () { P.bits.D = 0; } - void cmp_ay () { _cmp (_mem[_ay()]); } - void cmp_ax () { _cmp (_mem[_ax()]); } - void dec_ax () { _dec (_ax()); } + void bne() { if (Z) _bra(); PC++; } + void cmp_iy() { _cmp(_mem[_iy()]); } + void cmp_zx() { _cmp(_mem[_zx()]); } + void dec_zx() { _dec(_zx()); } + void cld() { P.bits.D = 0; } + void cmp_ay() { _cmp(_mem[_ay()]); } + void cmp_ax() { _cmp(_mem[_ax()]); } + void dec_ax() { _dec(_ax()); } // e0 - void cpx_ () { _cpx (_mem[PC++]); } - void sbc_ix () { _sbc (_mem[_ix()]); } - void cpx_z () { _cpx (_mem[_z()]); } - void sbc_z () { _sbc (_mem[_z()]); } - void inc_z () { _inc (_z()); } - void inx () { Z=N=++X; } - void sbc_ () { _sbc (_mem[PC++]); } - void cpx_a () { _cpx (_mem[_a()]); } - void sbc_a () { _sbc (_mem[_a()]); } - void inc_a () { _inc (_a()); } + void cpx_() { _cpx(_mem[PC++]); } + void sbc_ix() { _sbc(_mem[_ix()]); } + void cpx_z() { _cpx(_mem[_z()]); } + void sbc_z() { _sbc(_mem[_z()]); } + void inc_z() { _inc(_z()); } + void inx() { Z=N=++X; } + void sbc_() { _sbc(_mem[PC++]); } + void cpx_a() { _cpx(_mem[_a()]); } + void sbc_a() { _sbc(_mem[_a()]); } + void inc_a() { _inc(_a()); } // f0 - void beq () { if (!Z) _bra(); PC++; } - void sbc_iy () { _sbc (_mem[_iy()]); } - void sbc_zx () { _sbc (_mem[_zx()]); } - void inc_zx () { _inc (_zx()); } - void sed () { P.bits.D = 1; } - void sbc_ay () { _sbc (_mem[_ay()]); } - void sbc_ax () { _sbc (_mem[_ax()]); } - void inc_ax () { _inc (_ax()); } + void beq() { if (!Z) _bra(); PC++; } + void sbc_iy() { _sbc(_mem[_iy()]); } + void sbc_zx() { _sbc(_mem[_zx()]); } + void inc_zx() { _inc(_zx()); } + void sed() { P.bits.D = 1; } + void sbc_ay() { _sbc(_mem[_ay()]); } + void sbc_ax() { _sbc(_mem[_ax()]); } + void inc_ax() { _inc(_ax()); } }; #endif diff --git a/z80.cpp b/z80.cpp index 0d4e222..d500fbb 100644 --- a/z80.cpp +++ b/z80.cpp @@ -5,12 +5,9 @@ #include "CPU.h" #include "z80.h" -#define CPU_STATE_FMT - -char *z80::status() { - static char buf[256]; +char *z80::status(char *buf, size_t n) { byte op = _mem[PC]; - sprintf(buf, "_pc_ op _af_ _bc_ _de_ _hl_ _af' _bc' _de' _hl' _ir_ imff " + snprintf(buf, n, "_pc_ op _af_ _bc_ _de_ _hl_ _af' _bc' _de' _hl' _ir_ imff " "_sp_ sz5h3pnc\r\n" "%04x %02x %04x %04x %04x %04x %04x %04x %04x %04x %04x %d%d%d " "%04x %d%d%d%d%d%d%d%d\r\n", @@ -67,7 +64,7 @@ byte z80::_fetch_op() { _mc(PC, 4); byte op = _mem[PC]; #if defined(CPU_DEBUG) - _status("%5d MR %04x %02x\n", _ts, PC, op); + printf("%5d MR %04x %02x\n", _ts, PC, op); #endif PC++; R++; @@ -76,15 +73,11 @@ byte z80::_fetch_op() { void z80::run(unsigned clocks) { while (clocks--) { - step(); -#if !defined(CPU_DEBUG) - if (_halted) { - _status("CPU halted at %04x\r\n%s", PC, status()); - longjmp(_err, 1); - } -#endif - if (_irq_pending && _iff1) + if (_irq_pending) _handle_interrupt(); + step(); + if (_halted) + break; } } @@ -100,19 +93,25 @@ void z80::reset() { } void z80::_handle_interrupt() { - _iff1 = false; - _push(PC); - if (_irq_pending < 0) { // NMI - PC = 0x0066; - ts(11); - } else { - _iff2 = false; - R++; - if (_im == 0 || _im == 1) - PC = 0x0038; - else if (_im == 2) - PC = _rw(_irq_pending + (0x100 * I)); - ts(7); + if (_irq_pending < 0 || _iff1) { + if (_halted) { + _halted = false; + PC++; + } + _push(PC); + if (_irq_pending < 0) { // NMI + _iff2 = _iff1; + PC = 0x0066; + ts(11); + } else { + _iff1 = _iff2 = false; + R++; + if (_im == 0 || _im == 1) + PC = 0x0038; + else if (_im == 2) + PC = _rw(_irq_pending + (0x100 * I)); + ts(7); + } } _irq_pending = 0; } @@ -871,7 +870,7 @@ int z80::parity_table[] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, }; -z80::z80(Memory &m, jmp_buf &jb, CPU::statfn s, PortDevice &ports): CPU(m, jb, s) +z80::z80(Memory &m, PortDevice &ports): CPU(m) { _ports = &ports; _debug = false; diff --git a/z80.h b/z80.h index 13b14af..b1afaea 100644 --- a/z80.h +++ b/z80.h @@ -6,12 +6,12 @@ class z80: public CPU { public: - z80(Memory &, jmp_buf &, CPU::statfn, PortDevice &); + z80(Memory &, PortDevice &); void run(unsigned); void reset(); void raise(int level) { _irq_pending = level; } - char *status(); + char *status(char *buf, size_t n); void checkpoint(Stream &); void restore(Stream &); @@ -38,7 +38,6 @@ public: inline word iy() { return IY; } inline word sp() { return SP; } inline word pc() { return PC; } - inline bool halted() { return _halted; } inline bool iff1() { return _iff1; } inline bool iff2() { return _iff2; } inline byte im() { return _im; } @@ -137,7 +136,6 @@ private: bool _iff1, _iff2; unsigned long _ts; - bool _halted; int _irq_pending; PortDevice *_ports;