From 02dac91274df45ff45f237ab04756480c6af7957 Mon Sep 17 00:00:00 2001 From: Andrew Jacobs Date: Mon, 27 Jun 2016 20:24:56 +0100 Subject: [PATCH] Initial file import --- .gitignore | 2 + Makefile | 23 + emu816.cc | 521 +++++++++++++++++++ emu816.h | 1469 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mem816.cc | 15 + mem816.h | 50 ++ program.cc | 103 ++++ wdc816.cc | 20 + wdc816.h | 63 +++ 9 files changed, 2266 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 emu816.cc create mode 100644 emu816.h create mode 100644 mem816.cc create mode 100644 mem816.h create mode 100644 program.cc create mode 100644 wdc816.cc create mode 100644 wdc816.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c3c12cf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +emu816 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ca033fe --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ + +CPPFLAGS=-O + +all: emu816 + +clean: + $(RM) *.o + $(RM) emu816 + +emu816: wdc816.o emu816.o mem816.o program.o + g++ wdc816.o emu816.o mem816.o program.o -o emu816 + +wdc816.o: \ + wdc816.cc wdc816.h + +emu816.o: \ + emu816.cc emu816.h wdc816.h mem816.h + +mem816.o: \ + mem816.cc mem816.h wdc816.h + +program.o: \ + program.cc emu816.h mem816.h wdc816.h diff --git a/emu816.cc b/emu816.cc new file mode 100644 index 0000000..45a7786 --- /dev/null +++ b/emu816.cc @@ -0,0 +1,521 @@ + +// TODO: decimal mode + +#include "emu816.h" + +#ifdef CHIPKIT +#include "WProgram.h" +#else +# include +# include + +using namespace std; +#endif + +//============================================================================== +//------------------------------------------------------------------------------ + +emu816::emu816(mem816 &mem) + : mem(mem) +{ } + +emu816::~emu816() +{ } + +void emu816::reset() +{ + e = 1; + pbr = 0x00 << 16; + dbr = 0x00 << 16; + dp.w = 0x0000; + sp.w = 0x0100; + pc = mem.getWord(0xfffc); + p.b = 0x34; + + interrupted = false; +} + +void emu816::step() +{ + // Check for NMI/IRQ + + SHOWPC(); + + switch (mem.getByte (join(pbr, pc++))) { + case 0x00: op_brk(am_immb()); break; + case 0x01: op_ora(am_dpix()); break; + case 0x02: op_cop(am_immb()); break; + case 0x03: op_ora(am_srel()); break; + case 0x04: op_tsb(am_dpag()); break; + case 0x05: op_ora(am_dpag()); break; + case 0x06: op_asl(am_dpag()); break; + case 0x07: op_ora(am_dpil()); break; + case 0x08: op_php(am_impl()); break; + case 0x09: op_ora(am_immm()); break; + case 0x0a: op_asla(am_acc()); break; + case 0x0b: op_phd(am_impl()); break; + case 0x0c: op_tsb(am_absl()); break; + case 0x0d: op_ora(am_absl()); break; + case 0x0e: op_asl(am_absl()); break; + case 0x0f: op_ora(am_alng()); break; + + case 0x10: op_bpl(am_rela()); break; + case 0x11: op_ora(am_dpiy()); break; + case 0x12: op_ora(am_dpgi()); break; + case 0x13: op_ora(am_sriy()); break; + case 0x14: op_trb(am_dpag()); break; + case 0x15: op_ora(am_dpgx()); break; + case 0x16: op_asl(am_dpgx()); break; + case 0x17: op_ora(am_dily()); break; + case 0x18: op_clc(am_impl()); break; + case 0x19: op_ora(am_absy()); break; + case 0x1a: op_inca(am_acc()); break; + case 0x1b: op_tcs(am_impl()); break; + case 0x1c: op_trb(am_absl()); break; + case 0x1d: op_ora(am_absx()); break; + case 0x1e: op_asl(am_absx()); break; + case 0x1f: op_ora(am_alnx()); break; + + case 0x20: op_jsr(am_absl()); break; + case 0x21: op_and(am_dpix()); break; + case 0x22: op_jsl(am_alng()); break; + case 0x23: op_and(am_srel()); break; + case 0x24: op_bit(am_dpag()); break; + case 0x25: op_and(am_dpag()); break; + case 0x26: op_rol(am_dpag()); break; + case 0x27: op_and(am_dpil()); break; + case 0x28: op_plp(am_impl()); break; + case 0x29: op_and(am_immm()); break; + case 0x2a: op_rola(am_acc()); break; + case 0x2b: op_pld(am_impl()); break; + case 0x2c: op_bit(am_absl()); break; + case 0x2d: op_and(am_absl()); break; + case 0x2e: op_rol(am_absl()); break; + case 0x2f: op_and(am_alng()); break; + + case 0x30: op_bmi(am_rela()); break; + case 0x31: op_and(am_dpiy()); break; + case 0x32: op_and(am_dpgi()); break; + case 0x33: op_and(am_sriy()); break; + case 0x34: op_bit(am_dpgx()); break; + case 0x35: op_and(am_dpgx()); break; + case 0x36: op_rol(am_dpgx()); break; + case 0x37: op_and(am_dily()); break; + case 0x38: op_sec(am_impl()); break; + case 0x39: op_and(am_absy()); break; + case 0x3a: op_deca(am_acc()); break; + case 0x3b: op_tsc(am_impl()); break; + case 0x3c: op_bit(am_absx()); break; + case 0x3d: op_and(am_absx()); break; + case 0x3e: op_rol(am_absx()); break; + case 0x3f: op_and(am_alnx()); break; + + case 0x40: op_rti(am_impl()); break; + case 0x41: op_eor(am_dpix()); break; + case 0x42: op_wdm(am_immb()); break; + case 0x43: op_eor(am_srel()); break; + case 0x44: op_mvp(am_immw()); break; + case 0x45: op_eor(am_dpag()); break; + case 0x46: op_lsr(am_dpag()); break; + case 0x47: op_eor(am_dpil()); break; + case 0x48: op_pha(am_impl()); break; + case 0x49: op_eor(am_immm()); break; + case 0x4a: op_lsra(am_impl()); break; + case 0x4b: op_phk(am_impl()); break; + case 0x4c: op_jmp(am_absl()); break; + case 0x4d: op_eor(am_absl()); break; + case 0x4e: op_lsr(am_absl()); break; + case 0x4f: op_eor(am_alng()); break; + + case 0x50: op_bvc(am_rela()); break; + case 0x51: op_eor(am_dpiy()); break; + case 0x52: op_eor(am_dpgi()); break; + case 0x53: op_eor(am_sriy()); break; + case 0x54: op_mvn(am_immw()); break; + case 0x55: op_eor(am_dpgx()); break; + case 0x56: op_lsr(am_dpgx()); break; + case 0x57: op_eor(am_dpil()); break; + case 0x58: op_cli(am_impl()); break; + case 0x59: op_eor(am_absy()); break; + case 0x5a: op_phy(am_impl()); break; + case 0x5b: op_tcd(am_impl()); break; + case 0x5c: op_jmp(am_alng()); break; + case 0x5d: op_eor(am_absx()); break; + case 0x5e: op_lsr(am_absx()); break; + case 0x5f: op_eor(am_alnx()); break; + + case 0x60: op_rts(am_impl()); break; + case 0x61: op_adc(am_dpix()); break; + case 0x62: op_per(am_lrel()); break; + case 0x63: op_adc(am_srel()); break; + case 0x64: op_stz(am_dpag()); break; + case 0x65: op_adc(am_dpag()); break; + case 0x66: op_ror(am_dpag()); break; + case 0x67: op_adc(am_dpil()); break; + case 0x68: op_pla(am_impl()); break; + case 0x69: op_adc(am_immm()); break; + case 0x6a: op_rora(am_impl()); break; + case 0x6b: op_rtl(am_impl()); break; + case 0x6c: op_jmp(am_absi()); break; + case 0x6d: op_adc(am_absl()); break; + case 0x6e: op_ror(am_absl()); break; + case 0x6f: op_adc(am_alng()); break; + + case 0x70: op_bvs(am_rela()); break; + case 0x71: op_adc(am_dpiy()); break; + case 0x72: op_adc(am_dpgi()); break; + case 0x73: op_adc(am_sriy()); break; + case 0x74: op_stz(am_dpgx()); break; + case 0x75: op_adc(am_dpgx()); break; + case 0x76: op_ror(am_dpgx()); break; + case 0x77: op_adc(am_dily()); break; + case 0x78: op_sei(am_impl()); break; + case 0x79: op_adc(am_absy()); break; + case 0x7a: op_ply(am_impl()); break; + case 0x7b: op_tdc(am_impl()); break; + case 0x7c: op_jmp(am_abxi()); break; + case 0x7d: op_adc(am_absx()); break; + case 0x7e: op_ror(am_absx()); break; + case 0x7f: op_adc(am_alnx()); break; + + case 0x80: op_bra(am_rela()); break; + case 0x81: op_sta(am_dpix()); break; + case 0x82: op_brl(am_lrel()); break; + case 0x83: op_sta(am_srel()); break; + case 0x84: op_sty(am_dpag()); break; + case 0x85: op_sta(am_dpag()); break; + case 0x86: op_stx(am_dpag()); break; + case 0x87: op_sta(am_dpil()); break; + case 0x88: op_dey(am_impl()); break; + case 0x89: op_biti(am_immm()); break; + case 0x8a: op_txa(am_impl()); break; + case 0x8b: op_phb(am_impl()); break; + case 0x8c: op_sty(am_absl()); break; + case 0x8d: op_sta(am_absl()); break; + case 0x8e: op_stx(am_absl()); break; + case 0x8f: op_sta(am_alng()); break; + + case 0x90: op_bcc(am_rela()); break; + case 0x91: op_sta(am_dpiy()); break; + case 0x92: op_sta(am_dpgi()); break; + case 0x93: op_sta(am_sriy()); break; + case 0x94: op_sty(am_dpgx()); break; + case 0x95: op_sta(am_dpgx()); break; + case 0x96: op_stx(am_dpgy()); break; + case 0x97: op_sta(am_dily()); break; + case 0x98: op_tya(am_impl()); break; + case 0x99: op_sta(am_absy()); break; + case 0x9a: op_txs(am_impl()); break; + case 0x9b: op_txy(am_impl()); break; + case 0x9c: op_stz(am_absl()); break; + case 0x9d: op_sta(am_absx()); break; + case 0x9e: op_stz(am_absx()); break; + case 0x9f: op_sta(am_alnx()); break; + + case 0xa0: op_ldy(am_immx()); break; + case 0xa1: op_lda(am_dpix()); break; + case 0xa2: op_ldx(am_immx()); break; + case 0xa3: op_lda(am_srel()); break; + case 0xa4: op_ldy(am_dpag()); break; + case 0xa5: op_lda(am_dpag()); break; + case 0xa6: op_ldx(am_dpag()); break; + case 0xa7: op_lda(am_dpil()); break; + case 0xa8: op_tay(am_impl()); break; + case 0xa9: op_lda(am_immm()); break; + case 0xaa: op_tax(am_impl()); break; + case 0xab: op_plb(am_impl()); break; + case 0xac: op_ldy(am_absl()); break; + case 0xad: op_lda(am_absl()); break; + case 0xae: op_ldx(am_absl()); break; + case 0xaf: op_lda(am_alng()); break; + + case 0xb0: op_bcs(am_rela()); break; + case 0xb1: op_lda(am_dpiy()); break; + case 0xb2: op_lda(am_dpgi()); break; + case 0xb3: op_lda(am_sriy()); break; + case 0xb4: op_ldy(am_dpgx()); break; + case 0xb5: op_lda(am_dpgx()); break; + case 0xb6: op_ldx(am_dpgy()); break; + case 0xb7: op_lda(am_dpil()); break; + case 0xb8: op_clv(am_impl()); break; + case 0xb9: op_lda(am_absy()); break; + case 0xba: op_tsx(am_impl()); break; + case 0xbb: op_tyx(am_impl()); break; + case 0xbc: op_ldy(am_absx()); break; + case 0xbd: op_lda(am_absx()); break; + case 0xbe: op_ldx(am_absy()); break; + case 0xbf: op_lda(am_alng()); break; + + case 0xc0: op_cpy(am_immx()); break; + case 0xc1: op_cmp(am_dpix()); break; + case 0xc2: op_rep(am_immb()); break; + case 0xc3: op_cmp(am_srel()); break; + case 0xc4: op_cpy(am_dpag()); break; + case 0xc5: op_cmp(am_dpag()); break; + case 0xc6: op_dec(am_dpag()); break; + case 0xc7: op_cmp(am_dpil()); break; + case 0xc8: op_iny(am_impl()); break; + case 0xc9: op_cmp(am_immm()); break; + case 0xca: op_dex(am_impl()); break; + case 0xcb: op_wai(am_impl()); break; + case 0xcc: op_cpy(am_absl()); break; + case 0xcd: op_cmp(am_absl()); break; + case 0xce: op_dec(am_absl()); break; + case 0xcf: op_cmp(am_alng()); break; + + case 0xd0: op_bne(am_rela()); break; + case 0xd1: op_cmp(am_dpiy()); break; + case 0xd2: op_cmp(am_dpgi()); break; + case 0xd3: op_cmp(am_sriy()); break; + case 0xd4: op_pei(am_dpgi()); break; + case 0xd5: op_cmp(am_dpgx()); break; + case 0xd6: op_dec(am_dpgx()); break; + case 0xd7: op_cmp(am_dily()); break; + case 0xd8: op_cld(am_impl()); break; + case 0xd9: op_cmp(am_absy()); break; + case 0xda: op_phx(am_impl()); break; + case 0xdb: op_stp(am_impl()); break; + case 0xdc: op_jmp(am_abil()); break; + case 0xdd: op_cmp(am_absx()); break; + case 0xde: op_dec(am_absx()); break; + case 0xdf: op_cmp(am_alnx()); break; + + case 0xe0: op_cpx(am_immx()); break; + case 0xe1: op_sbc(am_dpix()); break; + case 0xe2: op_sep(am_immb()); break; + case 0xe3: op_sbc(am_srel()); break; + case 0xe4: op_cpx(am_dpag()); break; + case 0xe5: op_sbc(am_dpag()); break; + case 0xe6: op_inc(am_dpag()); break; + case 0xe7: op_sbc(am_dpil()); break; + case 0xe8: op_inx(am_impl()); break; + case 0xe9: op_sbc(am_immm()); break; + case 0xea: op_nop(am_impl()); break; + case 0xeb: op_xba(am_impl()); break; + case 0xec: op_cpx(am_absl()); break; + case 0xed: op_sbc(am_absl()); break; + case 0xee: op_inc(am_absl()); break; + case 0xef: op_sbc(am_alng()); break; + + case 0xf0: op_beq(am_rela()); break; + case 0xf1: op_sbc(am_dpiy()); break; + case 0xf2: op_sbc(am_dpgi()); break; + case 0xf3: op_sbc(am_sriy()); break; + case 0xf4: op_pea(am_immw()); break; + case 0xf5: op_sbc(am_dpgx()); break; + case 0xf6: op_inc(am_dpgx()); break; + case 0xf7: op_sbc(am_dily()); break; + case 0xf8: op_sed(am_impl()); break; + case 0xf9: op_sbc(am_absy()); break; + case 0xfa: op_plx(am_impl()); break; + case 0xfb: op_xce(am_impl()); break; + case 0xfc: op_jsr(am_abxi()); break; + case 0xfd: op_sbc(am_absx()); break; + case 0xfe: op_inc(am_absx()); break; + case 0xff: op_sbc(am_alnx()); break; + } + + ENDL(); +} + +//============================================================================== +// Debugging Utilities +//------------------------------------------------------------------------------ + +#ifdef CHIPKIT +void emu816::show() +{ + Serial.print (toHex(pbr, 2)); + Serial.print (':'); + Serial.print (toHex(pc, 4)); + Serial.print (' '); + Serial.print (toHex(mem.getByte(join(pbr, pc)), 2)); +} + +void emu816::bytes(unsigned int count) +{ + if (count > 0) { + Serial.print(' '); + Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 0)), 2)); + } + else + Serial.print(" "); + + if (count > 1) { + Serial.print(' '); + Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 1)), 2)); + } + else + Serial.print(" "); + + if (count > 2) { + Serial.print(' '); + Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 2)), 2)); + } + else + Serial.print(" "); + + Serial.print(' '); +} + +void emu816::dump(const char *mnem, Addr ea) +{ + Serial.print(mnem); + Serial.print(" {"); + Serial.print(toHex(ea, 4)); + Serial.print('}'); + + Serial.print(" E="); + Serial.print(toHex(e, 1)); + + Serial.print(" P="); + Serial.print(p.f_n ? 'N' : '.'); + Serial.print(p.f_v ? 'V' : '.'); + Serial.print(p.f_m ? 'M' : '.'); + Serial.print(p.f_x ? 'X' : '.'); + Serial.print(p.f_d ? 'D' : '.'); + Serial.print(p.f_i ? 'I' : '.'); + Serial.print(p.f_z ? 'Z' : '.'); + Serial.print(p.f_c ? 'C' : '.'); + + Serial.print(" A="); + if (e || p.f_m) { + Serial.print(toHex(hi(a.w), 2)); + Serial.print('['); + } + else { + Serial.print('['); + Serial.print(toHex(hi(a.w), 2)); + } + Serial.print(toHex(a.b, 2)); + Serial.print(']'); + + Serial.print(" X="); + if (e || p.f_x) { + Serial.print(toHex(hi(x.w), 2)); + Serial.print('['); + } + else { + Serial.print('['); + Serial.print(toHex(hi(x.w), 2)); + } + Serial.print(toHex(x.b, 2)); + Serial.print(']'); + + Serial.print(" Y="); + if (e || p.f_x) { + Serial.print(toHex(hi(y.w), 2)); + Serial.print('['); + } + else { + Serial.print('['); + Serial.print(toHex(hi(y.w), 2)); + } + Serial.print(toHex(y.b, 2)); + Serial.print(']'); + + Serial.print(" DP="); + Serial.print(toHex(dp.w, 4)); + + Serial.print(" SP="); + if (e) { + Serial.print(toHex(hi(sp.w), 2)); + Serial.print('['); + } + else { + Serial.print('['); + Serial.print(toHex(hi(sp.w), 2)); + } + Serial.print(toHex(sp.b, 2)); + Serial.print(']'); + + Serial.print(" {"); + Serial.print(' '); + Serial.print(toHex(mem.getByte(sp.w + 1), 2)); + Serial.print(' '); + Serial.print(toHex(mem.getByte(sp.w + 2), 2)); + Serial.print(' '); + Serial.print(toHex(mem.getByte(sp.w + 3), 2)); + Serial.print(' '); + Serial.print(toHex(mem.getByte(sp.w + 4), 2)); + Serial.print(" }"); + + Serial.print(" DBR="); + Serial.print(toHex(dbr, 2)); +} +#else +void emu816::show() +{ + cout << toHex(pbr, 2); + cout << ':' << toHex(pc, 4); + cout << ' ' << toHex(mem.getByte(join(pbr, pc)), 2); +} + +void emu816::bytes(unsigned int count) +{ + if (count > 0) + cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 0)), 2); + else + cout << " "; + + if (count > 1) + cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 1)), 2); + else + cout << " "; + + if (count > 2) + cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 2)), 2); + else + cout << " "; + + cout << ' '; +} + +void emu816::dump(const char *mnem, Addr ea) +{ + cout << mnem << " {" << toHex(ea, 4) << '}'; + + cout << " E=" << toHex(e, 1); + cout << " P=" << + (p.f_n ? 'N' : '.') << + (p.f_v ? 'V' : '.') << + (p.f_m ? 'M' : '.') << + (p.f_x ? 'X' : '.') << + (p.f_d ? 'D' : '.') << + (p.f_i ? 'I' : '.') << + (p.f_z ? 'Z' : '.') << + (p.f_c ? 'C' : '.'); + cout << " A="; + if (e || p.f_m) + cout << toHex(hi(a.w), 2) << '['; + else + cout << '[' << toHex(hi(a.w), 2); + cout << toHex(a.b, 2) << ']'; + cout << " X="; + if (e || p.f_x) + cout << toHex(hi(x.w), 2) << '['; + else + cout << '[' << toHex(hi(x.w), 2); + cout << toHex(x.b, 2) << ']'; + cout << " Y="; + if (e || p.f_x) + cout << toHex(hi(y.w), 2) << '['; + else + cout << '[' << toHex(hi(y.w), 2); + cout << toHex(y.b, 2) << ']'; + cout << " DP=" << toHex(dp.w, 4); + cout << " SP="; + if (e) + cout << toHex(hi(sp.w), 2) << '['; + else + cout << '[' << toHex(hi(sp.w), 2); + cout << toHex(sp.b, 2) << ']'; + cout << " {"; + cout << ' ' << toHex(mem.getByte(sp.w + 1), 2); + cout << ' ' << toHex(mem.getByte(sp.w + 2), 2); + cout << ' ' << toHex(mem.getByte(sp.w + 3), 2); + cout << ' ' << toHex(mem.getByte(sp.w + 4), 2); + cout << " }"; + cout << " DBR=" << toHex(dbr, 2); +} +#endif diff --git a/emu816.h b/emu816.h new file mode 100644 index 0000000..0443cea --- /dev/null +++ b/emu816.h @@ -0,0 +1,1469 @@ +#ifndef EMU816 +#define EMU816 +#include "mem816.h" + +#if 1 +# define TRACE(MNEM) { dump(MNEM, ea); } +# define BYTES(N) { bytes(N); pc += N; } +# define SHOWPC() { show(); } +# ifdef CHIPKIT +# define ENDL() { Serial.println (); } +# else +# define ENDL() { cout << endl; } +# endif +#else +# define TRACE(MNEM) +# define BYTES(N) { pc += N; } +# define SHOWPC() +# define ENDL() +#endif + +class emu816 : + public wdc816 +{ +public: + emu816(mem816 &mem); + ~emu816(); + + void reset(); + void step(); + +private: + union { + struct { + Bit f_c : 1; + Bit f_z : 1; + Bit f_i : 1; + Bit f_d : 1; + Bit f_x : 1; + Bit f_m : 1; + Bit f_v : 1; + Bit f_n : 1; + }; + Byte b; + } p; + + Bit e; + + union { + Byte b; + Word w; + } a, x, y, sp, dp; + + Word pc; + Byte pbr, dbr; + + mem816 &mem; + + bool interrupted; + unsigned long cycles; + + void show(); + void bytes(unsigned int); + void dump(const char *, Addr); + + INLINE void pushByte(Byte value) + { + mem.setByte(sp.w, value); + + if (e) + --sp.b; + else + --sp.w; + } + + INLINE void pushWord(Word value) + { + pushByte(hi(value)); + pushByte(lo(value)); + } + + INLINE Byte pullByte() + { + if (e) + ++sp.b; + else + ++sp.w; + + return (mem.getByte(sp.w)); + } + + INLINE Word pullWord() + { + register Byte l = pullByte(); + register Byte h = pullByte(); + + return (join(l, h)); + } + + // Absolute - a + INLINE Addr am_absl() + { + register Addr ea = join (dbr, mem.getWord(bank(pbr) | pc)); + + BYTES(2); + return (ea); + } + + // Absolute Indexed X - a,X + INLINE Addr am_absx() + { + register Addr ea = join(dbr, mem.getWord(bank(pbr) | pc)) + x.w; + + BYTES(2); + return (ea); + } + + // Absolute Indexed Y - a,Y + INLINE Addr am_absy() + { + register Addr ea = join(dbr, mem.getWord(bank(pbr) | pc)) + y.w; + + BYTES(2); + return (ea); + } + + // Absolute Indirect - (a) + INLINE Addr am_absi() + { + register Addr ia = join(0, mem.getWord(bank(pbr) | pc)); + + BYTES(2); + return (join(0, mem.getWord(ia))); + } + + // Absolute Indexed Indirect - (a,X) + INLINE Addr am_abxi() + { + register Addr ia = join(pbr, mem.getWord(bank(pbr) | pc)) + x.w; + + BYTES(2); + return (join(pbr, mem.getWord(ia))); + } + + // Absolute Long - >a + INLINE Addr am_alng() + { + Addr ea = mem.getAddr(bank(pbr) | pc); + + BYTES(3); + return (ea); + } + + // Absolute Long Indexed - >a,X + INLINE Addr am_alnx() + { + register Addr ea = mem.getAddr(bank(pbr) | pc) + x.w; + + BYTES(3); + return (ea); + } + + // Absolute Indirect Long - [a] + INLINE Addr am_abil() + { + register Addr ia = bank(0) | mem.getWord(bank(pbr) | pc); + + BYTES(2); + return (mem.getAddr(ia)); + } + + // Direct Page - d + INLINE Addr am_dpag() + { + Byte offset = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (bank(0) | (Word)(dp.w + offset)); + } + + // Direct Page Indexed X - d,X + INLINE Addr am_dpgx() + { + Byte offset = mem.getByte(bank(pbr) | pc) + x.b; + + BYTES(1); + return (bank(0) | (Word)(dp.w + offset)); + } + + // Direct Page Indexed Y - d,Y + INLINE Addr am_dpgy() + { + Byte offset = mem.getByte(bank(pbr) | pc) + y.b; + + BYTES(1); + return (bank(0) | (Word)(dp.w + offset)); + } + + // Direct Page Indirect - (d) + INLINE Addr am_dpgi() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (bank(dbr) | mem.getWord(bank(0) | (Word)(dp.w + disp))); + } + + // Direct Page Indexed Indirect - (d,x) + INLINE Addr am_dpix() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (bank(dbr) | mem.getWord(bank(0) | (Word)(dp.w + disp + x.w))); + } + + // Direct Page Indirect Indexed - (d),Y + INLINE Addr am_dpiy() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (bank(dbr) | mem.getWord(bank(0) | (dp.w + disp)) + y.w); + } + + // Direct Page Indirect Long - [d] + INLINE Addr am_dpil() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (mem.getAddr(bank(0) | (Word)(dp.w + disp))); + } + + // Direct Page Indirect Long Indexed - [d],Y + INLINE Addr am_dily() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (mem.getAddr(bank(0) | (Word)(dp.w + disp)) + y.w); + } + + // Implied/Stack + INLINE Addr am_impl() + { + BYTES(0); + return (0); + } + + // Accumulator + INLINE Addr am_acc() + { + BYTES(0); + return (0); + } + + // Immediate Byte + INLINE Addr am_immb() + { + Addr ea = bank(pbr) | pc; + + BYTES(1); + return (ea); + } + + // Immediate Word + INLINE Addr am_immw() + { + Addr ea = bank(pbr) | pc; + + BYTES(2); + return (ea); + } + + // Immediate based on size of A/M + INLINE Addr am_immm() + { + Addr ea = bank(pbr) | pc; + unsigned int size = (e || p.f_m) ? 1 : 2; + + BYTES(size); + return (ea); + } + + // Immediate based on size of X/Y + INLINE Addr am_immx() + { + Addr ea = bank(pbr) | pc; + unsigned int size = (e || p.f_x) ? 1 : 2; + + BYTES(size); + return (ea); + } + + INLINE Addr am_lrel() + { + Word disp = mem.getWord(bank(pbr) | pc); + + BYTES(2); + return (bank(pbr) | (Word)(pc + (signed short)disp)); + } + + INLINE Addr am_rela() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + return (bank(pbr) | (Word)(pc + (signed char)disp)); + } + + // Stack Relative - d,S + INLINE Addr am_srel() + { + Byte disp = mem.getByte(bank(pbr) | pc); + + BYTES(1); + + if (e) + return((bank(0) | join(sp.b + disp, hi(sp.w)))); + else + return (bank(0) | (Word)(sp.w + disp)); + } + + // Stack Relative Indirect Indexed Y - (d,S),Y + INLINE Addr am_sriy() + { + Byte disp = mem.getByte(bank(pbr) | pc); + register Word ia; + + BYTES(1); + + if (e) + ia = mem.getWord(join(sp.b + disp, hi(sp.w))); + else + ia = mem.getWord(bank(0) | (sp.w + disp)); + + return (bank(dbr) | (Word)(ia + y.w)); + } + + INLINE void setn(unsigned int flag) + { + p.f_n = flag ? 1 : 0; + } + + INLINE void setv(unsigned int flag) + { + p.f_v = flag ? 1 : 0; + } + + INLINE void setd(unsigned int flag) + { + p.f_d = flag ? 1 : 0; + } + + INLINE void seti(unsigned int flag) + { + p.f_i = flag ? 1 : 0; + } + + INLINE void setz(unsigned int flag) + { + p.f_z = flag ? 1 : 0; + } + + INLINE void setc(unsigned int flag) + { + p.f_c = flag ? 1 : 0; + } + + INLINE void setnz_b(Byte value) + { + setn(value & 0x80); + setz(value == 0); + } + + INLINE void setnz_w(Word value) + { + setn(value & 0x8000); + setz(value == 0); + } + + INLINE void op_adc(Addr ea) + { + TRACE("ADC"); + + if (e || p.f_m) { + Byte data = mem.getByte(ea); + Word temp = a.b + data + p.f_c; + + setc(temp & 0x100); + setv((~(a.b ^ data)) & (a.b ^ temp) & 0x80); + setnz_b(a.b = lo(temp)); + } + else { + Word data = mem.getWord(ea); + int temp = a.w + data + p.f_c; + + setc(temp & 0x100); + setv((~(a.w ^ data)) & (a.w ^ temp) & 0x8000); + setnz_w(a.w = (Word)temp); + } + } + + INLINE void op_and(Addr ea) + { + TRACE("AND"); + + if (e || p.f_m) + setnz_b(a.b &= mem.getByte(ea)); + else + setnz_w(a.w &= mem.getWord(ea)); + } + + INLINE void op_asl(Addr ea) + { + TRACE("ASL"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + setc(data & 0x80); + setnz_b(data <<= 1); + mem.setByte(ea, data); + } + else { + register Word data = mem.getWord(ea); + + setc(data & 0x8000); + setnz_w(data <<= 1); + mem.setWord(ea, data); + } + } + + INLINE void op_asla(Addr ea) + { + TRACE("ASL"); + + if (e || p.f_m) { + setc(a.b & 0x80); + setnz_b(a.b <<= 1); + mem.setByte(ea, a.b); + } + else { + setc(a.w & 0x8000); + setnz_w(a.w <<= 1); + mem.setWord(ea, a.w); + } + } + + INLINE void op_bcc(Addr ea) + { + TRACE("BCC"); + + if (p.f_c == 0) + pc = (Word)ea; + } + + INLINE void op_bcs(Addr ea) + { + TRACE("BCS"); + + if (p.f_c == 1) + pc = (Word)ea; + } + + INLINE void op_beq(Addr ea) + { + TRACE("BEQ"); + + if (p.f_z == 1) + pc = (Word)ea; + } + + INLINE void op_bit(Addr ea) + { + TRACE("BIT"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + setz((a.b & data) == 0); + setn(data & 0x80); + setv(data & 0x40); + } + else { + register Word data = mem.getWord(ea); + + setz((a.w & data) == 0); + setn(data & 0x8000); + setv(data & 0x4000); + } + } + + INLINE void op_biti(Addr ea) + { + TRACE("BIT"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + setz((a.b & data) == 0); + } + else { + register Word data = mem.getWord(ea); + + setz((a.w & data) == 0); + } + } + + INLINE void op_bmi(Addr ea) + { + TRACE("BMI"); + + if (p.f_n == 1) + pc = (Word)ea; + } + + INLINE void op_bne(Addr ea) + { + TRACE("BNE"); + + if (p.f_z == 0) + pc = (Word)ea; + } + + INLINE void op_bpl(Addr ea) + { + TRACE("BPL"); + + if (p.f_n == 0) + pc = (Word)ea; + } + + INLINE void op_bra(Addr ea) + { + TRACE("BRA"); + + pc = (Word)ea; + } + + INLINE void op_brk(Addr ea) + { + TRACE("BRK"); + + if (e) { + pushWord(pc); + pushByte(p.b | 0x10); + + p.f_i = 1; + p.f_d = 0; + pbr = 0; + + pc = mem.getWord(0xfffe); + } + else { + pushByte(pbr); + pushWord(pc); + pushByte(p.b); + + p.f_i = 1; + p.f_d = 0; + pbr = 0; + + pc = mem.getWord(0xffe6); + } + } + + INLINE void op_brl(Addr ea) + { + TRACE("BRL"); + + pc = (Word)ea; + } + + INLINE void op_bvc(Addr ea) + { + TRACE("BVC"); + + if (p.f_v == 0) + pc = (Word)ea; + } + + INLINE void op_bvs(Addr ea) + { + TRACE("BVS"); + + if (p.f_v == 1) + pc = (Word)ea; + } + + INLINE void op_clc(Addr ea) + { + TRACE("CLC"); + + setc(0); + } + + INLINE void op_cld(Addr ea) + { + TRACE("CLD") + + setd(0); + } + + INLINE void op_cli(Addr ea) + { + TRACE("CLI") + + seti(0); + } + + INLINE void op_clv(Addr ea) + { + TRACE("CLD") + + setv(0); + } + + INLINE void op_cmp(Addr ea) + { + TRACE("CMP"); + + if (e || p.f_m) { + Byte data = mem.getByte(ea); + Word temp = a.b - data; + + setc(temp & 0x100); + setnz_b(lo(temp)); + } + else { + Word data = mem.getWord(ea); + Addr temp = a.w - data; + + setc(temp & 0x10000L); + setnz_w((Word)temp); + } + } + + INLINE void op_cop(Addr ea) + { + TRACE("COP"); + + if (e) { + pushWord(pc); + pushByte(p.b); + + p.f_i = 1; + p.f_d = 0; + pbr = 0; + + pc = mem.getWord(0xfff4); + } + else { + pushByte(pbr); + pushWord(pc); + pushByte(p.b); + + p.f_i = 1; + p.f_d = 0; + pbr = 0; + + pc = mem.getWord(0xffe4); + } + } + + INLINE void op_cpx(Addr ea) + { + TRACE("CPX"); + + if (e || p.f_x) { + Byte data = mem.getByte(ea); + setnz_b(x.b - data); + setc(x.b >= data); + } + else { + Word data = mem.getWord(ea); + setnz_w(x.w - data); + setc(x.w >= data); + } + } + + INLINE void op_cpy(Addr ea) + { + TRACE("CPY"); + + if (e || p.f_x) { + Byte data = mem.getByte(ea); + setnz_b(y.b - data); + setc(y.b >= data); + } + else { + Word data = mem.getWord(ea); + setnz_w(y.w - data); + setc(y.w >= data); + } + } + + INLINE void op_dec(Addr ea) + { + TRACE("DEC"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + mem.setByte(ea, ++data); + setnz_b(data); + } + else { + register Word data = mem.getWord(ea); + + mem.setWord(ea, ++data); + setnz_w(data); + } + } + + INLINE void op_deca(Addr ea) + { + TRACE("DEC"); + + if (e || p.f_m) + setnz_b(--a.b); + else + setnz_w(--a.w); + } + + INLINE void op_dex(Addr ea) + { + TRACE("DEX"); + + if (e || p.f_x) + setnz_b(x.b -= 1); + else + setnz_w(x.w -= 1); + } + + INLINE void op_dey(Addr ea) + { + TRACE("DEY"); + + if (e || p.f_x) + setnz_b(y.b -= 1); + else + setnz_w(y.w -= 1); + } + + INLINE void op_eor(Addr ea) + { + TRACE("EOR"); + + if (e || p.f_m) + setnz_b(a.b ^= mem.getByte(ea)); + else + setnz_w(a.w ^= mem.getWord(ea)); + } + + INLINE void op_inc(Addr ea) + { + TRACE("INC"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + mem.setByte(ea, ++data); + setnz_b(data); + } + else { + register Word data = mem.getWord(ea); + + mem.setWord(ea, ++data); + setnz_w(data); + } + } + + INLINE void op_inca(Addr ea) + { + TRACE("INC"); + + if (e || p.f_m) + setnz_b(++a.b); + else + setnz_w(++a.w); + } + + INLINE void op_inx(Addr ea) + { + TRACE("INX"); + + if (e || p.f_x) + setnz_b(++x.b); + else + setnz_w(++x.w); + } + + INLINE void op_iny(Addr ea) + { + TRACE("INY"); + + if (e || p.f_x) + setnz_b(++y.b); + else + setnz_w(++y.w); + } + + INLINE void op_jmp(Addr ea) + { + TRACE("JMP"); + + pbr = lo(ea >> 16); + pc = (Word)ea; + } + + INLINE void op_jsl(Addr ea) + { + TRACE("JSL"); + + pushByte(pbr); + pushWord(pc - 1); + + pbr = lo(ea >> 16); + pc = (Word)ea; + } + + INLINE void op_jsr(Addr ea) + { + TRACE("JSR"); + + pushWord(pc - 1); + + pc = (Word)ea; + } + + INLINE void op_lda(Addr ea) + { + TRACE("LDA"); + + if (e || p.f_m) + setnz_b(a.b = mem.getByte(ea)); + else + setnz_w(a.w = mem.getWord(ea)); + } + + INLINE void op_ldx(Addr ea) + { + TRACE("LDX"); + + if (e || p.f_x) + setnz_b(lo(x.w = mem.getByte(ea))); + else + setnz_w(x.w = mem.getWord(ea)); + } + + INLINE void op_ldy(Addr ea) + { + TRACE("LDY"); + + if (e || p.f_x) + setnz_b(lo(y.w = mem.getByte(ea))); + else + setnz_w(y.w = mem.getWord(ea)); + } + + INLINE void op_lsr(Addr ea) + { + TRACE("LSR"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + setc(data & 0x01); + setnz_b(data >>= 1); + mem.setByte(ea, data); + } + else { + register Word data = mem.getWord(ea); + + setc(data & 0x0001); + setnz_w(data >>= 1); + mem.setWord(ea, data); + } + } + + INLINE void op_lsra(Addr ea) + { + TRACE("LSR"); + + if (e || p.f_m) { + setc(a.b & 0x01); + setnz_b(a.b >>= 1); + mem.setByte(ea, a.b); + } + else { + setc(a.w & 0x0001); + setnz_w(a.w >>= 1); + mem.setWord(ea, a.w); + } + } + + INLINE void op_mvn(Addr ea) + { + TRACE("MVN"); + } + + INLINE void op_mvp(Addr ea) + { + TRACE("MVP"); + } + + INLINE void op_nop(Addr ea) + { + TRACE("NOP"); + } + + INLINE void op_ora(Addr ea) + { + TRACE("ORA"); + + if (e || p.f_m) + setnz_b(a.b |= mem.getByte(ea)); + else + setnz_w(a.w |= mem.getWord(ea)); + } + + INLINE void op_pea(Addr ea) + { + TRACE("PEA"); + + pushWord(mem.getWord(ea)); + } + + INLINE void op_pei(Addr ea) + { + TRACE("PEI"); + } + + INLINE void op_per(Addr ea) + { + TRACE("PER"); + } + + INLINE void op_pha(Addr ea) + { + TRACE("PHA"); + + if (e || p.f_m) + pushByte(a.b); + else + pushWord(a.w); + } + + INLINE void op_phb(Addr ea) + { + TRACE("PHB"); + + pushByte(dbr); + } + + INLINE void op_phd(Addr ea) + { + TRACE("PHD"); + + pushWord(dp.w); + } + + INLINE void op_phk(Addr ea) + { + TRACE("PHK"); + + pushByte(pbr); + } + + INLINE void op_php(Addr ea) + { + TRACE("PHP"); + + pushByte(p.b); + } + + INLINE void op_phx(Addr ea) + { + TRACE("PHX"); + + if (e || p.f_x) + pushByte(x.b); + else + pushWord(x.w); + } + + INLINE void op_phy(Addr ea) + { + TRACE("PHY"); + + if (e || p.f_x) + pushByte(y.b); + else + pushWord(y.w); + } + + INLINE void op_pla(Addr ea) + { + TRACE("PLA"); + + if (e || p.f_m) + setnz_b(a.b = pullByte()); + else + setnz_w(a.w = pullWord()); + } + + INLINE void op_plb(Addr ea) + { + TRACE("PLB"); + + setnz_b(dbr = pullByte()); + } + + INLINE void op_pld(Addr ea) + { + TRACE("PLD"); + + setnz_w(dp.w = pullWord()); + } + + INLINE void op_plk(Addr ea) + { + TRACE("PLK"); + + setnz_b(dbr = pullByte()); + } + + INLINE void op_plp(Addr ea) + { + TRACE("PLP"); + + if (e) + p.b = pullByte() | 0x30; + else { + p.b = pullByte(); + + if (p.f_x) { + x.w = x.b; + y.w = y.b; + } + } + } + + INLINE void op_plx(Addr ea) + { + TRACE("PLX"); + + if (e || p.f_x) + setnz_b(lo(x.w = pullByte())); + else + setnz_w(x.w = pullWord()); + } + + INLINE void op_ply(Addr ea) + { + TRACE("PLY"); + + if (e || p.f_x) + setnz_b(lo(y.w = pullByte())); + else + setnz_w(y.w = pullWord()); + } + + INLINE void op_rep(Addr ea) + { + TRACE("REP"); + + p.b &= ~mem.getByte(ea); + if (e) p.f_m = p.f_x = 1; + } + + INLINE void op_rol(Addr ea) + { + TRACE("ROL"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + register Byte carry = p.f_c ? 0x01 : 0x00; + + setc(data & 0x80); + setnz_b(data = (data << 1) | carry); + mem.setByte(ea, data); + } + else { + register Word data = mem.getWord(ea); + register Word carry = p.f_c ? 0x0001 : 0x0000; + + setc(data & 0x8000); + setnz_w(data = (data << 1) | carry); + mem.setWord(ea, data); + } + } + + INLINE void op_rola(Addr ea) + { + TRACE("ROL"); + + if (e || p.f_m) { + register Byte carry = p.f_c ? 0x01 : 0x00; + + setc(a.b & 0x80); + setnz_b(a.b = (a.b << 1) | carry); + mem.setByte(ea, a.b); + } + else { + register Word carry = p.f_c ? 0x0001 : 0x0000; + + setc(a.w & 0x8000); + setnz_w(a.w = (a.w << 1) | carry); + mem.setWord(ea, a.w); + } + } + + INLINE void op_ror(Addr ea) + { + TRACE("ROR"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + register Byte carry = p.f_c ? 0x80 : 0x00; + + setc(data & 0x80); + setnz_b(data = (data >> 1) | carry); + mem.setByte(ea, data); + } + else { + register Word data = mem.getWord(ea); + register Word carry = p.f_c ? 0x8000 : 0x0000; + + setc(data & 0x8000); + setnz_w(data = (data >> 1) | carry); + mem.setWord(ea, data); + } + } + + INLINE void op_rora(Addr ea) + { + TRACE("ROR"); + + if (e || p.f_m) { + register Byte carry = p.f_c ? 0x80 : 0x00; + + setc(a.b & 0x80); + setnz_b(a.b = (a.b >> 1) | carry); + mem.setByte(ea, a.b); + } + else { + register Word carry = p.f_c ? 0x8000 : 0x0000; + + setc(a.w & 0x8000); + setnz_w(a.w = (a.w >> 1) | carry); + mem.setWord(ea, a.w); + } + } + + INLINE void op_rtl(Addr ea) + { + TRACE("RTL"); + + pc = pullWord(); + pbr = pullByte(); + } + + INLINE void op_rti(Addr ea) + { + TRACE("RTI"); + + if (e) { + p.b = pullByte(); + pc = pullWord(); + } + else { + p.b = pullByte(); + pc = pullWord(); + pbr = pullByte(); + } + p.f_i = 0; + } + + INLINE void op_rts(Addr ea) + { + TRACE("RTS"); + + pc = pullWord() + 1; + } + + INLINE void op_sbc(Addr ea) + { + TRACE("SBC"); + + if (e || p.f_m) { + Byte data = ~mem.getByte(ea); + Word temp = a.b + data + p.f_c; + + setc(temp & 0x100); + setv((~(a.b ^ data)) & (a.b ^ temp) & 0x80); + setnz_b(a.b = lo(temp)); + } + else { + Word data = ~mem.getWord(ea); + int temp = a.w + data + p.f_c; + + setc(temp & 0x100); + setv((~(a.w ^ data)) & (a.w ^ temp) & 0x8000); + setnz_w(a.w = (Word)temp); + } + } + + INLINE void op_sec(Addr ea) + { + TRACE("SEC"); + + setc(1); + } + + INLINE void op_sed(Addr ea) + { + TRACE("SED"); + + setd(1); + } + + INLINE void op_sei(Addr ea) + { + TRACE("SEI"); + + seti(1); + } + + INLINE void op_sep(Addr ea) + { + TRACE("SEP"); + + p.b |= mem.getByte(ea); + if (e) p.f_m = p.f_x = 1; + + if (p.f_x) { + x.w = x.b; + y.w = y.b; + } + } + + INLINE void op_sta(Addr ea) + { + TRACE("STA"); + + if (e || p.f_m) + mem.setByte(ea, a.b); + else + mem.setWord(ea, a.w); + } + + INLINE void op_stp(Addr ea) + { + TRACE("STP"); + + if (!interrupted) { + pc -= 1; + } + else + interrupted = false; + } + + INLINE void op_stx(Addr ea) + { + TRACE("STX"); + + if (e || p.f_x) + mem.setByte(ea, x.b); + else + mem.setWord(ea, x.w); + } + + INLINE void op_sty(Addr ea) + { + TRACE("STY"); + + if (e || p.f_x) + mem.setByte(ea, y.b); + else + mem.setWord(ea, y.w); + } + + INLINE void op_stz(Addr ea) + { + TRACE("STZ"); + + if (e || p.f_m) + mem.setByte(ea, 0); + else + mem.setWord(ea, 0); + } + + INLINE void op_tax(Addr ea) + { + TRACE("TAX"); + + if (e || p.f_x) + setnz_b(lo(x.w = a.b)); + else + setnz_w(x.w = a.w); + } + + INLINE void op_tay(Addr ea) + { + TRACE("TAY"); + + if (e || p.f_x) + setnz_b(lo(y.w = a.b)); + else + setnz_w(y.w = a.w); + } + + INLINE void op_tcd(Addr ea) + { + TRACE("TCD"); + + dp.w = a.w; + } + + INLINE void op_tdc(Addr ea) + { + TRACE("TDC"); + + if (e || p.f_m) + setnz_b(lo(a.w = dp.w)); + else + setnz_w(a.w = dp.w); + } + + INLINE void op_tcs(Addr ea) + { + TRACE("TCS"); + + sp.w = e ? (0x0100 | a.b) : a.w; + } + + INLINE void op_trb(Addr ea) + { + TRACE("TRB"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + mem.setByte(ea, data & ~a.b); + setz((a.b & data) == 0); + } + else { + register Word data = mem.getWord(ea); + + mem.setWord(ea, data & ~a.w); + setz((a.w & data) == 0); + } + } + + INLINE void op_tsb(Addr ea) + { + TRACE("TSB"); + + if (e || p.f_m) { + register Byte data = mem.getByte(ea); + + mem.setByte(ea, data | a.b); + setz((a.b & data) == 0); + } + else { + register Word data = mem.getWord(ea); + + mem.setWord(ea, data | a.w); + setz((a.w & data) == 0); + } + } + + INLINE void op_tsc(Addr ea) + { + TRACE("TSC"); + + if (e || p.f_m) + setnz_b(lo(a.w = sp.w)); + else + setnz_w(a.w = sp.w); + } + + INLINE void op_tsx(Addr ea) + { + TRACE("TSX"); + } + + INLINE void op_txa(Addr ea) + { + TRACE("TXA"); + } + + INLINE void op_txs(Addr ea) + { + TRACE("TXS"); + } + + INLINE void op_txy(Addr ea) + { + TRACE("TXY"); + + if (e || p.f_x) + setnz_b(lo(y.w = x.w)); + else + setnz_w(y.w = x.w); + } + + INLINE void op_tya(Addr ea) + { + TRACE("TYA"); + + if (e || p.f_m) + setnz_b(a.b = y.b); + else + setnz_w(a.w = p.f_x ? y.b : y.w); + } + + INLINE void op_tyx(Addr ea) + { + TRACE("TYX"); + + if (e || p.f_x) + setnz_b(lo(x.w = y.w)); + else + setnz_w(x.w = y.w); + } + + INLINE void op_wai(Addr ea) + { + TRACE("WAI"); + + if (!interrupted) { + pc -= 1; + } + else + interrupted = false; + } + + INLINE void op_wdm(Addr ea) + { + TRACE("WDM"); + } + + INLINE void op_xba(Addr ea) + { + TRACE("XBA"); + + a.w = swap(a.w); + setnz_b(a.b); + } + + INLINE void op_xce(Addr ea) + { + TRACE("XCE"); + + unsigned char oe = e; + + e = p.f_c; + p.f_c = oe; + + if (e) { + sp.w = 0x0100 | sp.b; + dp.w = 0x0000; + } + } +}; +#endif diff --git a/mem816.cc b/mem816.cc new file mode 100644 index 0000000..56b9bc3 --- /dev/null +++ b/mem816.cc @@ -0,0 +1,15 @@ + +#include "mem816.h" + +mem816::mem816(Addr memMask, Addr ramSize, const Byte *pROM) + : memMask(memMask), ramSize(ramSize), pROM(pROM) +{ + pRAM = new Byte[ramSize]; +} + +mem816::mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM) + : memMask(memMask), ramSize(ramSize), pRAM (pRAM), pROM(pROM) +{ } + +mem816::~mem816() +{ } diff --git a/mem816.h b/mem816.h new file mode 100644 index 0000000..2fb4f93 --- /dev/null +++ b/mem816.h @@ -0,0 +1,50 @@ +#ifndef MEM816 +#define MEM816 +#include "wdc816.h" + +class mem816 : + public wdc816 +{ +public: + mem816(Addr memMask, Addr ramSize, const Byte *pROM); + mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM); + ~mem816(); + + INLINE Byte getByte(Addr ea) + { + if ((ea &= memMask) < ramSize) + return (pRAM[ea]); + + return (pROM[ea - ramSize]); + } + + INLINE Word getWord(Addr ea) + { + return (join(getByte(ea + 0), getByte(ea + 1))); + } + + INLINE Addr getAddr(Addr ea) + { + return (join(getByte(ea + 0), getWord(ea + 0))); + } + + INLINE void setByte(Addr ea, Byte data) + { + if ((ea &= memMask) < ramSize) + pRAM[ea] = data; + } + + INLINE void setWord(Addr ea, Word data) + { + setByte(ea + 0, lo(data)); + setByte(ea + 1, hi(data)); + } + +private: + const Addr memMask; + const Addr ramSize; + + Byte *pRAM; + const Byte *pROM; +}; +#endif diff --git a/program.cc b/program.cc new file mode 100644 index 0000000..8ef756c --- /dev/null +++ b/program.cc @@ -0,0 +1,103 @@ + +#include +#include +#include + +using namespace std; + +#include "mem816.h" +#include "emu816.h" + +//============================================================================== +// Memory Definitions and Access +//------------------------------------------------------------------------------ + +#define RAM_SIZE (384 * 1024) +#define ROM_SIZE (128 * 1024L) +#define MEM_MASK (512 * 1024L - 1) + +// The ROM area 128K +const wdc816::Byte ROM[ROM_SIZE] = +{ + 0x00, 0x00, 0x00, +}; + +mem816 mem(MEM_MASK, RAM_SIZE, ROM); +emu816 emu(mem); + +//============================================================================== +//------------------------------------------------------------------------------ + +void setup() +{ + emu.reset(); +} + +void loop() +{ + emu.step(); +} + +//============================================================================== +//------------------------------------------------------------------------------ + +unsigned int toNybble(char ch) +{ + if ((ch >= '0') && (ch <= '9')) return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10); + if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10); + return (0); +} + +unsigned int toByte(string &str, int &offset) +{ + unsigned int h = toNybble(str[offset++]) << 4; + unsigned int l = toNybble(str[offset++]); + + return (h | l); +} + +unsigned long toAddr(string &str, int &offset) +{ + unsigned long h = toByte(str, offset) << 16; + unsigned long m = toByte(str, offset) << 8; + unsigned long l = toByte(str, offset); + + return (h | m | l); +} + +void load(char *filename) +{ + ifstream file(filename); + string line; + + if (file.is_open()) { + cout << ">> Loading S28: " << filename << endl; + + while (!file.eof()) { + file >> line; + if ((line[0] == 'S') && (line[1] == '2')) { + int offset = 2; + unsigned int count = toByte(line, offset); + unsigned long addr = toAddr(line, offset); + count -= 4; + while (count-- > 0) { + mem.setByte(addr++, toByte(line, offset)); + } + } + } + } + + file.close(); +} + +int main(int argc, char **argv) +{ + for (int index = 1; index < argc;) + load(argv[index++]); + + setup(); + for (;;) loop(); + + return(0); +} diff --git a/wdc816.cc b/wdc816.cc new file mode 100644 index 0000000..e306c10 --- /dev/null +++ b/wdc816.cc @@ -0,0 +1,20 @@ +#include "wdc816.h" + +wdc816::wdc816() +{ } + +wdc816::~wdc816() +{ } + +char *wdc816::toHex(unsigned long value, unsigned int digits) +{ + static char buffer[16]; + unsigned int offset = sizeof(buffer);; + + buffer[--offset] = 0; + while (digits-- > 0) { + buffer[--offset] = "0123456789ABCDEF"[value & 0xf]; + value >>= 4; + } + return (&(buffer[offset])); +} diff --git a/wdc816.h b/wdc816.h new file mode 100644 index 0000000..8cf963a --- /dev/null +++ b/wdc816.h @@ -0,0 +1,63 @@ +#ifndef WDC816 +#define WDC816 + +//#define CHIPKIT + +#ifdef CHIPKIT +#define INLINE inline +#else +#define INLINE inline +#endif + +class wdc816 +{ +public: + // Common types for memory and register sizes + typedef unsigned char Bit; + typedef unsigned char Byte; + typedef unsigned short Word; + typedef unsigned long Addr; + + wdc816 (); + ~wdc816(); + + // Convert a value to a hex string. + static char *toHex(unsigned long value, unsigned int digits); + + // Return the low byte of a word + INLINE static Byte lo(Word value) + { + return ((Byte) value); + } + + // Return the high byte of a word + INLINE static Byte hi(Word value) + { + return (lo(value >> 8)); + } + + // Convert the bank number into a address + INLINE static Addr bank(Byte b) + { + return (b << 16); + } + + // Combine two bytes into a word + INLINE static Word join(Byte l, Byte h) + { + return (l | (h << 8)); + } + + // Combine a bank and an word into an address + INLINE static Addr join(Byte b, Word a) + { + return (bank(b) | a); + } + + // Swap the high and low bytes of a word + INLINE static Word swap(Word value) + { + return ((value >> 8) | (value << 8)); + } +}; +#endif