#ifndef __I8080_H__ #define __I8080_H__ #undef sbi #undef PC class i8080: public CPU { public: i8080(Memory &, PortDevice &); void run(unsigned); void reset(); void raise(int); char *status(char *buf, size_t n, bool hdr); void checkpoint(Stream &); void restore(Stream &); inline uint8_t a() { return A; } inline uint8_t b() { return B; } inline uint8_t c() { return C; } inline uint8_t d() { return D; } inline uint8_t e() { return E; } inline uint8_t h() { return H; } inline uint8_t l() { return L; } inline uint16_t bc() { return BC; } inline uint16_t de() { return DE; } inline uint16_t hl() { return HL; } inline uint8_t sr() { return SR; } private: uint8_t A; union { struct { uint8_t C, B; }; uint16_t BC; }; union { struct { uint8_t E, D; }; uint16_t DE; }; union { struct { uint8_t L, H; }; uint16_t HL; }; Memory::address SP; union { struct { unsigned C:1; unsigned __:1; // always 1 unsigned P:1; unsigned _:1; // always 0 unsigned H:1; unsigned I:1; unsigned Z:1; unsigned S:1; } flags; uint8_t SR; }; int _irq_pending; PortDevice *_ports; typedef void (i8080::*OP)(); OP _ops[256]; static int parity_table[256]; inline uint16_t _rw(Memory::address a) { return _mem[a] + (_mem[a+1] << 8); } inline void _sw(Memory::address a, uint16_t w) { _mem[a] = (w & 0xff); _mem[a+1] = (w >> 8); } inline void _szp(uint8_t r) { flags.S = ((r & 0x80) != 0); flags.Z = (r == 0); flags.P = parity_table[r]; } inline void _szhp(uint8_t b, uint8_t r) { _szp(r); flags.H = ((b & 0x0f) > (r & 0x0f)); } inline void _inc(uint8_t &b) { uint16_t w = b + 1; uint8_t r = w & 0xff; _szhp(b, r); b = r; } inline void _dec(uint8_t &b) { uint16_t w = b - 1; uint8_t r = w & 0xff; _szhp(b, r); b = r; } inline void _sr(uint8_t b) { SR = b; flags._ = 0; flags.__ = 1; } inline void _dad(uint16_t w) { unsigned long r = HL + w; HL = (r & 0xffff); flags.C = (r > 0xffff); } void nop() {} void lxib() { BC = _rw(PC); PC += 2; } void staxb() { _mem[BC] = A; } void inxb() { BC++; } void inrb() { _inc(B); } void dcrb() { _dec(B); } void mvib() { B = _mem[PC++]; } void rlc() { flags.C = ((A & 0x80) >> 7); A = (A << 1) | flags.C; } void dadb() { _dad(BC); } void ldaxb() { A = _mem[BC]; } void dcxb() { BC--; } void inrc() { _inc(C); } void dcrc() { _dec(C); } void mvic() { C = _mem[PC++]; } void rrc() { flags.C = (A & 0x01); A = (A >> 1) | (flags.C << 7); } void lxid() { DE = _rw(PC); PC += 2; } void staxd() { _mem[DE] = A; } void inxd() { DE++; } void inrd() { _inc(D); } void dcrd() { _dec(D); } void mvid() { D = _mem[PC++]; } void ral() { uint8_t b = (A << 1) | flags.C; flags.C = (A & 0x80) >> 7; A = b; } void dadd() { _dad(DE); } void ldaxd() { A = _mem[DE]; } void dcxd() { DE--; } void inre() { _inc(E); } void dcre() { _dec(E); } void mvie() { E = _mem[PC++]; } void rar() { uint8_t b = (A >> 1) | (flags.C << 7); flags.C = (A & 1); A = b; } void lxih() { HL = _rw(PC); PC += 2; } void shld() { _sw(_rw(PC), HL); PC += 2; } void inxh() { HL++; } void inrh() { _inc(H); } void dcrh() { _dec(H); } void mvih() { H = _mem[PC++]; } void daa(); void dadh() { _dad(HL); } void lhld() { HL = _rw(_rw(PC)); PC += 2; } void dcxh() { HL--; } void inrl() { _inc(L); } void dcrl() { _dec(L); } void mvil() { L = _mem[PC++]; } void cma() { A = ~A; } void lxisp() { SP = _rw(PC); PC += 2; } void sta() { _mem[_rw(PC)] = A; PC += 2; } void inxsp() { SP++; } void inrm() { uint8_t b = _mem[HL]; _inc(b); _mem[HL] = b; } void dcrm() { uint8_t b = _mem[HL]; _dec(b); _mem[HL] = b; } void mvim() { uint8_t b = _mem[PC++]; _mem[HL] = b; } void stc() { flags.C = 1; } void dadsp() { _dad(SP); } void lda() { A = _mem[_rw(PC)]; PC += 2; } void dcxsp() { SP--; } void inra() { _inc(A); } void dcra() { _dec(A); } void mvia() { A = _mem[PC++]; } void cmc() { flags.C = !flags.C; } void movbb() {} void movbc() { B = C; } void movbd() { B = D; } void movbe() { B = E; } void movbh() { B = H; } void movbl() { B = L; } void movbm() { B = _mem[HL]; } void movba() { B = A; } void movcb() { C = B; } void movcc() {} void movcd() { C = D; } void movce() { C = E; } void movch() { C = H; } void movcl() { C = L; } void movcm() { C = _mem[HL]; } void movca() { C = A; } void movdb() { D = B; } void movdc() { D = C; } void movdd() {} void movde() { D = E; } void movdh() { D = H; } void movdl() { D = L; } void movdm() { D = _mem[HL]; } void movda() { D = A; } void moveb() { E = B; } void movec() { E = C; } void moved() { E = D; } void movee() {} void moveh() { E = H; } void movel() { E = L; } void movem() { E = _mem[HL]; } void movea() { E = A; } void movhb() { H = B; } void movhc() { H = C; } void movhd() { H = D; } void movhe() { H = E; } void movhh() {} void movhl() { H = L; } void movhm() { H = _mem[HL]; } void movha() { H = A; } void movlb() { L = B; } void movlc() { L = C; } void movld() { L = D; } void movle() { L = E; } void movlh() { L = H; } void movll() {} void movlm() { L = _mem[HL]; } void movla() { L = A; } void movmb() { _mem[HL] = B; } void movmc() { _mem[HL] = C; } void movmd() { _mem[HL] = D; } void movme() { _mem[HL] = E; } void movmh() { _mem[HL] = H; } void movml() { _mem[HL] = L; } void hlt() { _halted = true; PC--; } void movma() { _mem[HL] = A; } void movab() { A = B; } void movac() { A = C; } void movad() { A = D; } void movae() { A = E; } void movah() { A = H; } void moval() { A = L; } void movam() { A = _mem[HL]; } void movaa() {} inline void _add(uint8_t x) { uint16_t w = A + x; uint8_t b = A; A = w & 0xff; _szhp(b, A); flags.C = w > 0xff; } void addb() { _add(B); } void addc() { _add(C); } void addd() { _add(D); } void adde() { _add(E); } void addh() { _add(H); } void addl() { _add(L); } void addm() { _add(_mem[HL]); } void adda() { _add(A); } inline void _adc(uint8_t x) { uint16_t w = A + x + flags.C; uint8_t b = A; A = w & 0xff; _szhp(b, A); flags.C = w > 0xff; } void adcb() { _adc(B); } void adcc() { _adc(C); } void adcd() { _adc(D); } void adce() { _adc(E); } void adch() { _adc(H); } void adcl() { _adc(L); } void adcm() { _adc(_mem[HL]); } void adca() { _adc(A); } inline void _sub(uint8_t x) { uint16_t w = A - x; uint8_t b = A; A = w & 0xff; _szhp(b, A); flags.C = w > 0xff; } void subb() { _sub(B); } void subc() { _sub(C); } void subd() { _sub(D); } void sube() { _sub(E); } void subh() { _sub(H); } void subl() { _sub(L); } void subm() { _sub(_mem[HL]); } void suba() { _sub(A); } inline void _sbc(uint8_t x) { uint16_t w = A - x - flags.C; uint8_t b = A; A = w & 0xff; _szhp(b, A); flags.C = w > 0xff; } void sbbb() { _sbc(B); } void sbbc() { _sbc(C); } void sbbd() { _sbc(D); } void sbbe() { _sbc(E); } void sbbh() { _sbc(H); } void sbbl() { _sbc(L); } void sbbm() { _sbc(_mem[HL]); } void sbba() { _sbc(A); } inline void _and(uint8_t b) { A = A & b; _szp(A); flags.C = 0; flags.H = 1; } void anab() { _and(B); } void anac() { _and(C); } void anad() { _and(D); } void anae() { _and(E); } void anah() { _and(H); } void anal() { _and(L); } void anam() { _and(_mem[HL]); } void anaa() { _and(A); } inline void _xor(uint8_t b) { A = A ^ b; _szp(A); flags.C = flags.H = 0; } void xrab() { _xor(B); } void xrac() { _xor(C); } void xrad() { _xor(D); } void xrae() { _xor(E); } void xrah() { _xor(H); } void xral() { _xor(L); } void xram() { _xor(_mem[HL]); } void xraa() { _xor(A); } inline void _or(uint8_t b) { A = A | b; _szp(A); flags.C = flags.H = 0; } void orab() { _or(B); } void orac() { _or(C); } void orad() { _or(D); } void orae() { _or(E); } void orah() { _or(H); } void oral() { _or(L); } void oram() { _or(_mem[HL]); } void oraa() { _or(A); } inline void _cmp(uint8_t b) { uint16_t w = A - b; _szhp(b, w & 0xff); flags.C = w > 0xff; } void cmpb() { _cmp(B); } void cmpc() { _cmp(C); } void cmpd() { _cmp(D); } void cmpe() { _cmp(E); } void cmph() { _cmp(H); } void cmpl() { _cmp(L); } void cmpm() { _cmp(_mem[HL]); } void cmpa() { _cmp(A); } inline uint8_t _popb() { return _mem[SP++]; } inline void _pushb(uint8_t b) { _mem[--SP] = b; } inline uint16_t _pop() { uint16_t w = _rw(SP); SP += 2; return w; } inline void _push(uint16_t w) { SP -= 2; _sw(SP, w); } inline void _jmp(uint8_t c) { if (c) jmp(); else PC += 2; } inline void _ret(uint8_t c) { if (c) ret(); } inline void _call(uint8_t c) { if (c) call(); else PC += 2; } void rnz() { _ret(!flags.Z); } void popb() { BC = _pop(); } void jnz() { _jmp(!flags.Z); } void jmp() { PC = _rw(PC); } void cnz() { _call(!flags.Z); } void pushb() { _push(BC); } void adi() { _add(_mem[PC++]); } void rst0() { _push(PC); PC = 0x00; } void rz() { _ret(flags.Z); } void ret() { PC = _pop(); } void jz() { _jmp(flags.Z); } void cz() { _call(flags.Z); } void call() { _push(PC+2); PC = _rw(PC); } void aci() { _adc(_mem[PC++]); } void rst1() { _push(PC); PC = 0x08; } void rnc() { _ret(!flags.C); } void popd() { DE = _pop(); } void jnc() { _jmp(!flags.C); } void out() { _ports->out(_mem[PC++], A, this); } void cnc() { _call(!flags.C); } void pushd() { _push(DE); } void sui() { _sub(_mem[PC++]); } void rst2() { _push(PC); PC = 0x10; } void rc() { _ret(flags.C); } void jc() { _jmp(flags.C); } void in() { A = _ports->in(_mem[PC++], this); } void cc() { _call(flags.C); } void sbi() { _sbc(_mem[PC++]); } void rst3() { _push(PC); PC = 0x18; } void rpo() { _ret(!flags.P); } void poph() { HL = _pop(); } void jpo() { _jmp(!flags.P); } void xthl() { uint16_t w = _pop(); _push(HL); HL = w; } void cpo() { _call(!flags.P); } void pushh() { _push(HL); } void ani() { _and(_mem[PC++]); } void rst4() { _push(PC); PC = 0x20; } void rpe() { _ret(flags.P); } void pchl() { PC = HL; } void jpe() { _jmp(flags.P); } void xchg() { uint16_t w = DE; DE = HL; HL = w; } void cpe() { _call(flags.P); } void xri() { _xor(_mem[PC++]); } void rst5() { _push(PC); PC = 0x28; } void rp() { _ret(!flags.S); } void pop() { _sr(_popb()); A = _popb(); } void jp() { _jmp(!flags.S); } void di() { flags.I = 0; } void cp() { _call(!flags.S); } void push() { _pushb(A); _pushb(SR); } void ori() { _or(_mem[PC++]); } void rst6() { _push(PC); PC = 0x30; } void rm() { _ret(flags.S); } void sphl() { SP = HL; } void jm() { _jmp(flags.S); } void ei(); void cm() { _call(flags.S); } void cpi() { _cmp(_mem[PC++]); } void rst7() { _push(PC); PC = 0x38; } }; #endif