r65emu/r6502.h

322 lines
9.7 KiB
C++

#ifndef __R6502_H__
#define __R6502_H__
#undef PC
#undef cli
#undef sei
class Stream;
class r6502: public CPU {
public:
void raise(uint8_t);
void reset();
void run(unsigned);
char *status(char *buf, size_t n, bool hdr=false);
void checkpoint(Stream &);
void restore(Stream &);
r6502(Memory &m): CPU(m) {}
private:
/* registers */
uint8_t S, A, X, Y;
uint8_t N, V, B, D, I, Z, C;
union {
struct {
unsigned C:1;
unsigned Z:1;
unsigned I:1;
unsigned D:1;
unsigned B:1;
unsigned _:1; // unused
unsigned V:1;
unsigned N:1;
} bits;
uint8_t flags;
} P;
bool _irq; // interrupt pending?
void irq();
void nmi();
uint8_t flags();
/* stack */
inline void pusha(Memory::address ret) {
_mem[0x0100+S--] = ret >> 8;
_mem[0x0100+S--] = ret & 0xff;
}
inline void pushb(uint8_t b) {
_mem[0x0100+S--] = b;
}
inline uint8_t popb() {
return _mem[++S+0x0100];
}
inline Memory::address popa() {
uint8_t b = popb();
return (popb() << 8) | b;
}
static const Memory::address nmivec = 0xfffa;
static const Memory::address resvec = 0xfffc;
static const Memory::address ibvec = 0xfffe;
inline Memory::address vector(Memory::address v) {
return (_mem[v+1] << 8) | _mem[v];
}
/* operators */
inline void _cmp(uint8_t a) { Z=N=A-a; C=(A>=a); }
inline void _cpx(uint8_t a) { Z=N=X-a; C=(X>=a); }
inline void _cpy(uint8_t a) { Z=N=Y-a; C=(Y>=a); }
inline void _and(uint8_t a) { Z=N=A&=a; }
inline void _eor(uint8_t a) { Z=N=A^=a; }
inline void _ora(uint8_t a) { Z=N=A|=a; }
inline void _lda(uint8_t a) { Z=N=A=a; }
inline void _ldx(uint8_t a) { Z=N=X=a; }
inline void _ldy(uint8_t a) { Z=N=Y=a; }
/* modes */
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) {
return (_mem[a+1]<<8)|_mem[a];
}
inline Memory::address _ix() { return _i(_zx()); }
inline Memory::address _iy() { return _i(_mem[PC++])+Y; }
void _adc(uint8_t a);
void _sbc(uint8_t a) {
if (P.bits.D) sbcd(a); else _adc(~a);
}
void sbcd(uint8_t a);
inline uint8_t __ror(uint8_t b) {
N=b>>1; if (C) N|=0x80; C=b&1; return Z=N;
}
inline void _ror(Memory::address a) {
_mem[a] = __ror(_mem[a]);
}
inline uint8_t __rol(uint8_t b) {
N=b<<1; if (C) N|=1; C=(b&0x80)!=0; return Z=N;
}
inline void _rol(Memory::address a) {
_mem[a] = __rol(_mem[a]);
}
inline uint8_t __asl(uint8_t b) {
C=(b&0x80)!=0; return Z=N=b<<1;
}
inline void _asl(Memory::address a) {
_mem[a] = __asl(_mem[a]);
}
inline uint8_t __lsr(uint8_t 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) {
Z=N=1+_mem[a]; _mem[a]=Z;
}
inline void _dec(Memory::address a) {
Z=N=_mem[a]-1; _mem[a]=Z;
}
inline void _bit(uint8_t z) {
V=((z & 0x40)!=0); N=(z & 0x80); Z=(A & z);
}
inline void _bra() {
uint8_t b = _mem[PC];
PC += b;
if (b > 127) PC -= 0x0100;
}
void _op(uint8_t);
/* operations */
inline void brk();
inline void ora_ix() { _ora(_mem[_ix()]); }
inline void ill() { --PC; _halted = true; }
inline void nop2() { PC++; }
inline void ora_z() { _ora(_mem[_z()]); }
inline void asl_z() { _asl(_z()); }
inline void php();
inline void ora_() { _ora(_mem[PC++]); }
inline void asl() { C=(A&0x80)!=0; Z=N=A<<=1; }
inline void nop3() { PC+=2; }
inline void ora_a() { _ora(_mem[_a()]); }
inline void asl_a() { _asl(_a()); }
// 10
inline void bpl() { if (!(N & 0x80)) _bra(); PC++; }
inline void ora_iy() { _ora(_mem[_iy()]); }
inline void ora_zx() { _ora(_mem[_zx()]); }
inline void asl_zx() { _asl(_zx()); }
inline void clc() { C=0; }
inline void ora_ay() { _ora(_mem[_ay()]); }
inline void nop() {}
inline void ora_ax() { _ora(_mem[_ax()]); }
inline void asl_ax() { _asl(_ax()); }
// 20
inline void jsr() { pusha(PC+1); PC = vector(PC); }
inline void and_ix() { _and(_mem[_ix()]); }
inline void bit_z() { _bit(_mem[_z()]); }
inline void and_z() { _and(_mem[_z()]); }
inline void rol_z() { _rol(_z()); }
void plp();
inline void and_() { _and(_mem[PC++]); }
inline void rol() { A=__rol(A); }
inline void bit_a() { _bit(_mem[_a()]); }
inline void and_a() { _and(_mem[_a()]); }
inline void rol_a() { _rol(_a()); }
// 30
inline void bmi() { if (N & 0x80) _bra(); PC++; }
inline void and_iy() { _and(_mem[_iy()]); }
inline void and_zx() { _and(_mem[_zx()]); }
inline void rol_zx() { _rol(_zx()); }
inline void sec() { C=1; }
inline void and_ay() { _and(_mem[_ay()]); }
inline void and_ax() { _and(_mem[_ax()]); }
inline void rol_ax() { _rol(_ax()); }
// 40
inline void rti() { plp(); PC = popa(); }
inline void eor_ix() { _eor(_mem[_ix()]); }
inline void eor_z() { _eor(_mem[_z()]); }
inline void lsr_z() { _lsr(_z()); }
inline void pha() { pushb(A); }
inline void eor_() { _eor(_mem[PC++]); }
inline void lsr_() { A=__lsr(A); }
inline void jmp() { PC = _a(); }
inline void eor_a() { _eor(_mem[_a()]); }
inline void lsr_a() { _lsr(_a()); }
// 50
inline void bvc() { if (!V) _bra(); PC++; }
inline void eor_iy() { _eor(_mem[_iy()]); }
inline void eor_zx() { _eor(_mem[_zx()]); }
inline void lsr_zx() { _lsr(_zx()); }
inline void cli() { P.bits.I = 0; if (_irq) irq(); }
inline void eor_ay() { _eor(_mem[_ay()]); }
inline void eor_ax() { _eor(_mem[_ax()]); }
inline void lsr_ax() { _lsr(_ax()); }
// 60
inline void rts() { PC = popa()+1; }
inline void adc_ix() { _adc(_mem[_ix()]); }
inline void adc_z() { _adc(_mem[_z()]); }
inline void ror_z() { _ror(_z()); }
inline void pla() { Z=N=A=popb(); }
inline void adc_() { _adc(_mem[PC++]); }
inline void ror_() { A=__ror(A); }
inline void jmp_i() { PC = _i(_a()); }
inline void adc_a() { _adc(_mem[_a()]); }
inline void ror_a() { _ror(_a()); }
// 70
inline void bvs() { if (V) _bra(); PC++; }
inline void adc_iy() { _adc(_mem[_iy()]); }
inline void adc_zx() { _adc(_mem[_zx()]); }
inline void ror_zx() { _ror(_zx()); }
inline void sei() { P.bits.I = 1; }
inline void adc_ay() { _adc(_mem[_ay()]); }
inline void adc_ax() { _adc(_mem[_ax()]); }
inline void ror_ax() { _ror(_ax()); }
// 80
inline void sta_ix() { _mem[_ix()] = A; }
inline void sty_z() { _mem[_z()] = Y; }
inline void sta_z() { _mem[_z()] = A; }
inline void stx_z() { _mem[_z()] = X; }
inline void dey() { Z=N=--Y; }
inline void txa() { Z=N=A=X; }
inline void sty_a() { _mem[_a()] = Y; }
inline void sta_a() { _mem[_a()] = A; }
inline void stx_a() { _mem[_a()] = X; }
// 90
inline void bcc() { if (!C) _bra(); PC++; }
inline void sta_iy() { _mem[_iy()] = A; }
inline void sty_zx() { _mem[_zx()] = Y; }
inline void sta_zx() { _mem[_zx()] = A; }
inline void stx_zy() { _mem[_zy()] = X; }
inline void tya() { Z=N=A=Y; }
inline void sta_ay() { _mem[_ay()] = A; }
inline void txs() { S=X; }
inline void sta_ax() { _mem[_ax()] = A; }
// a0
inline void ldy_() { _ldy(_mem[PC++]); }
inline void lda_ix() { _lda(_mem[_ix()]); }
inline void ldx_() { _ldx(_mem[PC++]); }
inline void lax_ix() { lda_ix(); X=A; }
inline void ldy_z() { _ldy(_mem[_z()]); }
inline void lda_z() { _lda(_mem[_z()]); }
inline void ldx_z() { _ldx(_mem[_z()]); }
inline void lax_z() { lda_z(); X=A; }
inline void tay() { Z=N=Y=A; }
inline void lda_() { _lda(_mem[PC++]); }
inline void tax() { Z=N=X=A; }
inline void ldy_a() { _ldy(_mem[_a()]); }
inline void lda_a() { _lda(_mem[_a()]); }
inline void ldx_a() { _ldx(_mem[_a()]); }
inline void lax_a() { lda_a(); X=A; }
// b0
inline void bcs() { if (C) _bra(); PC++; }
inline void lda_iy() { _lda(_mem[_iy()]); }
inline void lax_iy() { lda_iy(); X=A; }
inline void ldy_zx() { _ldy(_mem[_zx()]); }
inline void lda_zx() { _lda(_mem[_zx()]); }
inline void ldx_zy() { _ldx(_mem[_zy()]); }
inline void lax_zy() { ldx_zy(); A=X; }
inline void clv() { V=0; }
inline void lda_ay() { _lda(_mem[_ay()]); }
inline void tsx() { Z=N=X=S; }
inline void ldy_ax() { _ldy(_mem[_ax()]); }
inline void lda_ax() { _lda(_mem[_ax()]); }
inline void ldx_ay() { _ldx(_mem[_ay()]); }
inline void lax_ay() { ldx_ay(); A=X; }
// c0
inline void cpy_() { _cpy(_mem[PC++]); }
inline void cmp_ix() { _cmp(_mem[_ix()]); }
inline void cpy_z() { _cpy(_mem[_z()]); }
inline void cmp_z() { _cmp(_mem[_z()]); }
inline void dec_z() { _dec(_z()); }
inline void iny() { Z=N=++Y; }
inline void cmp_() { _cmp(_mem[PC++]); }
inline void dex() { Z=N=--X; }
inline void cpy_a() { _cpy(_mem[_a()]); }
inline void cmp_a() { _cmp(_mem[_a()]); }
inline void dec_a() { _dec(_a()); }
// d0
inline void bne() { if (Z) _bra(); PC++; }
inline void cmp_iy() { _cmp(_mem[_iy()]); }
inline void cmp_zx() { _cmp(_mem[_zx()]); }
inline void dec_zx() { _dec(_zx()); }
inline void cld() { P.bits.D = 0; }
inline void cmp_ay() { _cmp(_mem[_ay()]); }
inline void cmp_ax() { _cmp(_mem[_ax()]); }
inline void dec_ax() { _dec(_ax()); }
// e0
inline void cpx_() { _cpx(_mem[PC++]); }
inline void sbc_ix() { _sbc(_mem[_ix()]); }
inline void cpx_z() { _cpx(_mem[_z()]); }
inline void sbc_z() { _sbc(_mem[_z()]); }
inline void inc_z() { _inc(_z()); }
inline void inx() { Z=N=++X; }
inline void sbc_() { _sbc(_mem[PC++]); }
inline void cpx_a() { _cpx(_mem[_a()]); }
inline void sbc_a() { _sbc(_mem[_a()]); }
inline void inc_a() { _inc(_a()); }
// f0
inline void beq() { if (!Z) _bra(); PC++; }
inline void sbc_iy() { _sbc(_mem[_iy()]); }
inline void sbc_zx() { _sbc(_mem[_zx()]); }
inline void inc_zx() { _inc(_zx()); }
inline void sed() { P.bits.D = 1; }
inline void sbc_ay() { _sbc(_mem[_ay()]); }
inline void sbc_ax() { _sbc(_mem[_ax()]); }
inline void inc_ax() { _inc(_ax()); }
};
#endif