diff --git a/README.md b/README.md index 3146008..9342ab1 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,15 @@ The repository contains the source code for a simple 65C816 emulator for Windows, Linux and the embedded ChipKIT platform. -This is the first release of the code and it has only had a limited amount of +This is the second release of the code and it has only had a limited amount of testing. Currently there is no support for decimal arithmetic but the full instruction set is supported. +The major change since the last release has been the recoding of all the classes +to make them static. This was done to increase the execution performance of the +code. On my development laptop (AMD8 1.8GHz) it now runs at an emulated speed of +around 225 MHz with full optimization. + There is no I/O at the moment or source of interrupts. Executing a WDM #$FF will cause the emulator to exit. diff --git a/emu816.cc b/emu816.cc index 2afbe0d..adde706 100644 --- a/emu816.cc +++ b/emu816.cc @@ -9,7 +9,7 @@ // // A Portable C++ WDC 65C816 Emulator //------------------------------------------------------------------------------ -// Copyright (C)2016 Andrew John Jacobs +// Copyright (C),2016 Andrew John Jacobs // All rights reserved. // // This work is made available under the terms of the Creative Commons @@ -32,14 +32,32 @@ using namespace std; #endif +union emu816::FLAGS emu816::p; + +emu816::Bit emu816::e; + +union emu816::REGS emu816::a; +union emu816::REGS emu816::x; +union emu816::REGS emu816::y; +union emu816::REGS emu816::sp; +union emu816::REGS emu816::dp; + +emu816::Word emu816::pc; +emu816::Byte emu816::pbr; +emu816::Byte emu816::dbr; + +bool emu816::stopped; +bool emu816::interrupted; +unsigned long emu816::cycles; +bool emu816::trace; + //============================================================================== -// Construct a emu816 instance. -emu816::emu816(mem816 &mem) - : mem(mem) +// Not used. +emu816::emu816() { } -// Destroy a emu816 instance. +// Not used emu816::~emu816() { } @@ -51,13 +69,13 @@ void emu816::reset(bool trace) dbr = 0x00 << 16; dp.w = 0x0000; sp.w = 0x0100; - pc = mem.getWord(0xfffc); + pc = getWord(0xfffc); p.b = 0x34; stopped = false; interrupted = false; - this -> trace = trace; + emu816::trace = trace; } // Execute a single instruction or invoke an interrupt @@ -67,7 +85,7 @@ void emu816::step() SHOWPC(); - switch (mem.getByte (join(pbr, pc++))) { + switch (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; @@ -357,7 +375,7 @@ void emu816::show() Serial.print (':'); Serial.print (toHex(pc, 4)); Serial.print (' '); - Serial.print (toHex(mem.getByte(join(pbr, pc)), 2)); + Serial.print (toHex(getByte(join(pbr, pc)), 2)); } // Display the operand bytes @@ -365,21 +383,21 @@ void emu816::bytes(unsigned int count) { if (count > 0) { Serial.print(' '); - Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 0)), 2)); + Serial.print(toHex(getByte(bank(pbr) | (pc + 0)), 2)); } else Serial.print(" "); if (count > 1) { Serial.print(' '); - Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 1)), 2)); + Serial.print(toHex(getByte(bank(pbr) | (pc + 1)), 2)); } else Serial.print(" "); if (count > 2) { Serial.print(' '); - Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 2)), 2)); + Serial.print(toHex(getByte(bank(pbr) | (pc + 2)), 2)); } else Serial.print(" "); @@ -461,13 +479,13 @@ void emu816::dump(const char *mnem, Addr ea) Serial.print(" {"); Serial.print(' '); - Serial.print(toHex(mem.getByte(sp.w + 1), 2)); + Serial.print(toHex(getByte(sp.w + 1), 2)); Serial.print(' '); - Serial.print(toHex(mem.getByte(sp.w + 2), 2)); + Serial.print(toHex(getByte(sp.w + 2), 2)); Serial.print(' '); - Serial.print(toHex(mem.getByte(sp.w + 3), 2)); + Serial.print(toHex(getByte(sp.w + 3), 2)); Serial.print(' '); - Serial.print(toHex(mem.getByte(sp.w + 4), 2)); + Serial.print(toHex(getByte(sp.w + 4), 2)); Serial.print(" }"); Serial.print(" DBR="); @@ -480,24 +498,24 @@ void emu816::show() cout << '{' << toHex(cycles, 4) << "} "; cout << toHex(pbr, 2); cout << ':' << toHex(pc, 4); - cout << ' ' << toHex(mem.getByte(join(pbr, pc)), 2); + cout << ' ' << toHex(getByte(join(pbr, pc)), 2); } // Display the operand bytes void emu816::bytes(unsigned int count) { if (count > 0) - cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 0)), 2); + cout << ' ' << toHex(getByte(bank(pbr) | (pc + 0)), 2); else cout << " "; if (count > 1) - cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 1)), 2); + cout << ' ' << toHex(getByte(bank(pbr) | (pc + 1)), 2); else cout << " "; if (count > 2) - cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 2)), 2); + cout << ' ' << toHex(getByte(bank(pbr) | (pc + 2)), 2); else cout << " "; @@ -545,10 +563,10 @@ void emu816::dump(const char *mnem, Addr ea) 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 << ' ' << toHex(getByte(sp.w + 1), 2); + cout << ' ' << toHex(getByte(sp.w + 2), 2); + cout << ' ' << toHex(getByte(sp.w + 3), 2); + cout << ' ' << toHex(getByte(sp.w + 4), 2); cout << " }"; cout << " DBR=" << toHex(dbr, 2) << endl; } diff --git a/emu816.h b/emu816.h index 95f0953..07a5ab7 100644 --- a/emu816.h +++ b/emu816.h @@ -9,7 +9,7 @@ // // A Portable C++ WDC 65C816 Emulator //------------------------------------------------------------------------------ -// Copyright (C)2016 Andrew John Jacobs +// Copyright (C),2016 Andrew John Jacobs // All rights reserved. // // This work is made available under the terms of the Creative Commons @@ -26,7 +26,7 @@ #include -#if 1 +#if 0 # define TRACE(MNEM) { if (trace) dump(MNEM, ea); } # define BYTES(N) { if (trace) bytes(N); pc += N; } # define SHOWPC() { if (trace) show(); } @@ -42,28 +42,26 @@ # define ENDL() #endif +// Defines the WDC 65C816 emulator. class emu816 : - public wdc816 + public mem816 { public: - emu816(mem816 &mem); - ~emu816(); + static void reset(bool trace); + static void step(); - void reset(bool trace); - void step(); - - INLINE unsigned long getCycles() const + INLINE static unsigned long getCycles() { return (cycles); } - INLINE bool isStopped() const + INLINE static bool isStopped() { return (stopped); } private: - union { + static union FLAGS { struct { Bit f_c : 1; Bit f_z : 1; @@ -77,31 +75,32 @@ private: Byte b; } p; - Bit e; + static Bit e; - union { + static union REGS { Byte b; Word w; } a, x, y, sp, dp; - Word pc; - Byte pbr, dbr; + static Word pc; + static Byte pbr, dbr; - mem816 &mem; + static bool stopped; + static bool interrupted; + static unsigned long cycles; + static bool trace; - bool stopped; - bool interrupted; - unsigned long cycles; - bool trace; + emu816(); + ~emu816(); - void show(); - void bytes(unsigned int); - void dump(const char *, Addr); + static void show(); + static void bytes(unsigned int); + static void dump(const char *, Addr); // Push a byte on the stack - INLINE void pushByte(Byte value) + INLINE static void pushByte(Byte value) { - mem.setByte(sp.w, value); + setByte(sp.w, value); if (e) --sp.b; @@ -110,25 +109,25 @@ private: } // Push a word on the stack - INLINE void pushWord(Word value) + INLINE static void pushWord(Word value) { pushByte(hi(value)); pushByte(lo(value)); } // Pull a byte from the stack - INLINE Byte pullByte() + INLINE static Byte pullByte() { if (e) ++sp.b; else ++sp.w; - return (mem.getByte(sp.w)); + return (getByte(sp.w)); } // Pull a word from the stack - INLINE Word pullWord() + INLINE static Word pullWord() { register Byte l = pullByte(); register Byte h = pullByte(); @@ -137,9 +136,9 @@ private: } // Absolute - a - INLINE Addr am_absl() + INLINE static Addr am_absl() { - register Addr ea = join (dbr, mem.getWord(bank(pbr) | pc)); + register Addr ea = join (dbr, getWord(bank(pbr) | pc)); BYTES(2); cycles += 2; @@ -147,9 +146,9 @@ private: } // Absolute Indexed X - a,X - INLINE Addr am_absx() + INLINE static Addr am_absx() { - register Addr ea = join(dbr, mem.getWord(bank(pbr) | pc)) + x.w; + register Addr ea = join(dbr, getWord(bank(pbr) | pc)) + x.w; BYTES(2); cycles += 2; @@ -157,9 +156,9 @@ private: } // Absolute Indexed Y - a,Y - INLINE Addr am_absy() + INLINE static Addr am_absy() { - register Addr ea = join(dbr, mem.getWord(bank(pbr) | pc)) + y.w; + register Addr ea = join(dbr, getWord(bank(pbr) | pc)) + y.w; BYTES(2); cycles += 2; @@ -167,29 +166,29 @@ private: } // Absolute Indirect - (a) - INLINE Addr am_absi() + INLINE static Addr am_absi() { - register Addr ia = join(0, mem.getWord(bank(pbr) | pc)); + register Addr ia = join(0, getWord(bank(pbr) | pc)); BYTES(2); cycles += 4; - return (join(0, mem.getWord(ia))); + return (join(0, getWord(ia))); } // Absolute Indexed Indirect - (a,X) - INLINE Addr am_abxi() + INLINE static Addr am_abxi() { - register Addr ia = join(pbr, mem.getWord(bank(pbr) | pc)) + x.w; + register Addr ia = join(pbr, getWord(bank(pbr) | pc)) + x.w; BYTES(2); cycles += 4; - return (join(pbr, mem.getWord(ia))); + return (join(pbr, getWord(ia))); } // Absolute Long - >a - INLINE Addr am_alng() + INLINE static Addr am_alng() { - Addr ea = mem.getAddr(bank(pbr) | pc); + Addr ea = getAddr(bank(pbr) | pc); BYTES(3); cycles += 3; @@ -197,9 +196,9 @@ private: } // Absolute Long Indexed - >a,X - INLINE Addr am_alnx() + INLINE static Addr am_alnx() { - register Addr ea = mem.getAddr(bank(pbr) | pc) + x.w; + register Addr ea = getAddr(bank(pbr) | pc) + x.w; BYTES(3); cycles += 3; @@ -207,19 +206,19 @@ private: } // Absolute Indirect Long - [a] - INLINE Addr am_abil() + INLINE static Addr am_abil() { - register Addr ia = bank(0) | mem.getWord(bank(pbr) | pc); + register Addr ia = bank(0) | getWord(bank(pbr) | pc); BYTES(2); cycles += 5; - return (mem.getAddr(ia)); + return (getAddr(ia)); } // Direct Page - d - INLINE Addr am_dpag() + INLINE static Addr am_dpag() { - Byte offset = mem.getByte(bank(pbr) | pc); + Byte offset = getByte(bank(pbr) | pc); BYTES(1); cycles += 1; @@ -227,9 +226,9 @@ private: } // Direct Page Indexed X - d,X - INLINE Addr am_dpgx() + INLINE static Addr am_dpgx() { - Byte offset = mem.getByte(bank(pbr) | pc) + x.b; + Byte offset = getByte(bank(pbr) | pc) + x.b; BYTES(1); cycles += 1; @@ -237,9 +236,9 @@ private: } // Direct Page Indexed Y - d,Y - INLINE Addr am_dpgy() + INLINE static Addr am_dpgy() { - Byte offset = mem.getByte(bank(pbr) | pc) + y.b; + Byte offset = getByte(bank(pbr) | pc) + y.b; BYTES(1); cycles += 1; @@ -247,71 +246,71 @@ private: } // Direct Page Indirect - (d) - INLINE Addr am_dpgi() + INLINE static Addr am_dpgi() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 3; - return (bank(dbr) | mem.getWord(bank(0) | (Word)(dp.w + disp))); + return (bank(dbr) | getWord(bank(0) | (Word)(dp.w + disp))); } // Direct Page Indexed Indirect - (d,x) - INLINE Addr am_dpix() + INLINE static Addr am_dpix() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 3; - return (bank(dbr) | mem.getWord(bank(0) | (Word)(dp.w + disp + x.w))); + return (bank(dbr) | getWord(bank(0) | (Word)(dp.w + disp + x.w))); } // Direct Page Indirect Indexed - (d),Y - INLINE Addr am_dpiy() + INLINE static Addr am_dpiy() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 3; - return (bank(dbr) | mem.getWord(bank(0) | (dp.w + disp)) + y.w); + return (bank(dbr) | getWord(bank(0) | (dp.w + disp)) + y.w); } // Direct Page Indirect Long - [d] - INLINE Addr am_dpil() + INLINE static Addr am_dpil() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 4; - return (mem.getAddr(bank(0) | (Word)(dp.w + disp))); + return (getAddr(bank(0) | (Word)(dp.w + disp))); } // Direct Page Indirect Long Indexed - [d],Y - INLINE Addr am_dily() + INLINE static Addr am_dily() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 4; - return (mem.getAddr(bank(0) | (Word)(dp.w + disp)) + y.w); + return (getAddr(bank(0) | (Word)(dp.w + disp)) + y.w); } // Implied/Stack - INLINE Addr am_impl() + INLINE static Addr am_impl() { BYTES(0); return (0); } // Accumulator - INLINE Addr am_acc() + INLINE static Addr am_acc() { BYTES(0); return (0); } // Immediate Byte - INLINE Addr am_immb() + INLINE static Addr am_immb() { Addr ea = bank(pbr) | pc; @@ -321,7 +320,7 @@ private: } // Immediate Word - INLINE Addr am_immw() + INLINE static Addr am_immw() { Addr ea = bank(pbr) | pc; @@ -331,7 +330,7 @@ private: } // Immediate based on size of A/M - INLINE Addr am_immm() + INLINE static Addr am_immm() { Addr ea = bank(pbr) | pc; unsigned int size = (e || p.f_m) ? 1 : 2; @@ -342,7 +341,7 @@ private: } // Immediate based on size of X/Y - INLINE Addr am_immx() + INLINE static Addr am_immx() { Addr ea = bank(pbr) | pc; unsigned int size = (e || p.f_x) ? 1 : 2; @@ -353,9 +352,9 @@ private: } // Long Relative - d - INLINE Addr am_lrel() + INLINE static Addr am_lrel() { - Word disp = mem.getWord(bank(pbr) | pc); + Word disp = getWord(bank(pbr) | pc); BYTES(2); cycles += 2; @@ -363,9 +362,9 @@ private: } // Relative - d - INLINE Addr am_rela() + INLINE static Addr am_rela() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 1; @@ -373,9 +372,9 @@ private: } // Stack Relative - d,S - INLINE Addr am_srel() + INLINE static Addr am_srel() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); BYTES(1); cycles += 1; @@ -387,78 +386,78 @@ private: } // Stack Relative Indirect Indexed Y - (d,S),Y - INLINE Addr am_sriy() + INLINE static Addr am_sriy() { - Byte disp = mem.getByte(bank(pbr) | pc); + Byte disp = getByte(bank(pbr) | pc); register Word ia; BYTES(1); cycles += 3; if (e) - ia = mem.getWord(join(sp.b + disp, hi(sp.w))); + ia = getWord(join(sp.b + disp, hi(sp.w))); else - ia = mem.getWord(bank(0) | (sp.w + disp)); + ia = getWord(bank(0) | (sp.w + disp)); return (bank(dbr) | (Word)(ia + y.w)); } // Set the Negative flag - INLINE void setn(unsigned int flag) + INLINE static void setn(unsigned int flag) { p.f_n = flag ? 1 : 0; } // Set the Overflow flag - INLINE void setv(unsigned int flag) + INLINE static void setv(unsigned int flag) { p.f_v = flag ? 1 : 0; } // Set the decimal flag - INLINE void setd(unsigned int flag) + INLINE static void setd(unsigned int flag) { p.f_d = flag ? 1 : 0; } // Set the Interrupt Disable flag - INLINE void seti(unsigned int flag) + INLINE static void seti(unsigned int flag) { p.f_i = flag ? 1 : 0; } // Set the Zero flag - INLINE void setz(unsigned int flag) + INLINE static void setz(unsigned int flag) { p.f_z = flag ? 1 : 0; } // Set the Carry flag - INLINE void setc(unsigned int flag) + INLINE static void setc(unsigned int flag) { p.f_c = flag ? 1 : 0; } // Set the Negative and Zero flags from a byte value - INLINE void setnz_b(Byte value) + INLINE static void setnz_b(Byte value) { setn(value & 0x80); setz(value == 0); } // Set the Negative and Zero flags from a word value - INLINE void setnz_w(Word value) + INLINE static void setnz_w(Word value) { setn(value & 0x8000); setz(value == 0); } - INLINE void op_adc(Addr ea) + INLINE static void op_adc(Addr ea) { TRACE("ADC"); if (e || p.f_m) { - Byte data = mem.getByte(ea); + Byte data = getByte(ea); Word temp = a.b + data + p.f_c; setc(temp & 0x100); @@ -467,7 +466,7 @@ private: cycles += 2; } else { - Word data = mem.getWord(ea); + Word data = getWord(ea); int temp = a.w + data + p.f_c; setc(temp & 0x100); @@ -477,60 +476,60 @@ private: } } - INLINE void op_and(Addr ea) + INLINE static void op_and(Addr ea) { TRACE("AND"); if (e || p.f_m) { - setnz_b(a.b &= mem.getByte(ea)); + setnz_b(a.b &= getByte(ea)); cycles += 2; } else { - setnz_w(a.w &= mem.getWord(ea)); + setnz_w(a.w &= getWord(ea)); cycles += 3; } } - INLINE void op_asl(Addr ea) + INLINE static void op_asl(Addr ea) { TRACE("ASL"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); setc(data & 0x80); setnz_b(data <<= 1); - mem.setByte(ea, data); + setByte(ea, data); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); setc(data & 0x8000); setnz_w(data <<= 1); - mem.setWord(ea, data); + setWord(ea, data); cycles += 5; } } - INLINE void op_asla(Addr ea) + INLINE static 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); + setByte(ea, a.b); } else { setc(a.w & 0x8000); setnz_w(a.w <<= 1); - mem.setWord(ea, a.w); + setWord(ea, a.w); } cycles += 2; } - INLINE void op_bcc(Addr ea) + INLINE static void op_bcc(Addr ea) { TRACE("BCC"); @@ -543,7 +542,7 @@ private: cycles += 2; } - INLINE void op_bcs(Addr ea) + INLINE static void op_bcs(Addr ea) { TRACE("BCS"); @@ -556,7 +555,7 @@ private: cycles += 2; } - INLINE void op_beq(Addr ea) + INLINE static void op_beq(Addr ea) { TRACE("BEQ"); @@ -569,12 +568,12 @@ private: cycles += 2; } - INLINE void op_bit(Addr ea) + INLINE static void op_bit(Addr ea) { TRACE("BIT"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); setz((a.b & data) == 0); setn(data & 0x80); @@ -582,7 +581,7 @@ private: cycles += 2; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); setz((a.w & data) == 0); setn(data & 0x8000); @@ -592,24 +591,24 @@ private: } } - INLINE void op_biti(Addr ea) + INLINE static void op_biti(Addr ea) { TRACE("BIT"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); setz((a.b & data) == 0); } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); setz((a.w & data) == 0); } cycles += 2; } - INLINE void op_bmi(Addr ea) + INLINE static void op_bmi(Addr ea) { TRACE("BMI"); @@ -622,7 +621,7 @@ private: cycles += 2; } - INLINE void op_bne(Addr ea) + INLINE static void op_bne(Addr ea) { TRACE("BNE"); @@ -635,7 +634,7 @@ private: cycles += 2; } - INLINE void op_bpl(Addr ea) + INLINE static void op_bpl(Addr ea) { TRACE("BPL"); @@ -648,7 +647,7 @@ private: cycles += 2; } - INLINE void op_bra(Addr ea) + INLINE static void op_bra(Addr ea) { TRACE("BRA"); @@ -657,7 +656,7 @@ private: cycles += 3; } - INLINE void op_brk(Addr ea) + INLINE static void op_brk(Addr ea) { TRACE("BRK"); @@ -669,7 +668,7 @@ private: p.f_d = 0; pbr = 0; - pc = mem.getWord(0xfffe); + pc = getWord(0xfffe); cycles += 7; } else { @@ -681,12 +680,12 @@ private: p.f_d = 0; pbr = 0; - pc = mem.getWord(0xffe6); + pc = getWord(0xffe6); cycles += 8; } } - INLINE void op_brl(Addr ea) + INLINE static void op_brl(Addr ea) { TRACE("BRL"); @@ -694,7 +693,7 @@ private: cycles += 3; } - INLINE void op_bvc(Addr ea) + INLINE static void op_bvc(Addr ea) { TRACE("BVC"); @@ -707,7 +706,7 @@ private: cycles += 2; } - INLINE void op_bvs(Addr ea) + INLINE static void op_bvs(Addr ea) { TRACE("BVS"); @@ -720,7 +719,7 @@ private: cycles += 2; } - INLINE void op_clc(Addr ea) + INLINE static void op_clc(Addr ea) { TRACE("CLC"); @@ -728,7 +727,7 @@ private: cycles += 2; } - INLINE void op_cld(Addr ea) + INLINE static void op_cld(Addr ea) { TRACE("CLD") @@ -736,7 +735,7 @@ private: cycles += 2; } - INLINE void op_cli(Addr ea) + INLINE static void op_cli(Addr ea) { TRACE("CLI") @@ -744,7 +743,7 @@ private: cycles += 2; } - INLINE void op_clv(Addr ea) + INLINE static void op_clv(Addr ea) { TRACE("CLD") @@ -752,12 +751,12 @@ private: cycles += 2; } - INLINE void op_cmp(Addr ea) + INLINE static void op_cmp(Addr ea) { TRACE("CMP"); if (e || p.f_m) { - Byte data = mem.getByte(ea); + Byte data = getByte(ea); Word temp = a.b - data; setc(temp & 0x100); @@ -765,7 +764,7 @@ private: cycles += 2; } else { - Word data = mem.getWord(ea); + Word data = getWord(ea); Addr temp = a.w - data; setc(temp & 0x10000L); @@ -774,7 +773,7 @@ private: } } - INLINE void op_cop(Addr ea) + INLINE static void op_cop(Addr ea) { TRACE("COP"); @@ -786,7 +785,7 @@ private: p.f_d = 0; pbr = 0; - pc = mem.getWord(0xfff4); + pc = getWord(0xfff4); cycles += 7; } else { @@ -798,68 +797,68 @@ private: p.f_d = 0; pbr = 0; - pc = mem.getWord(0xffe4); + pc = getWord(0xffe4); cycles += 8; } } - INLINE void op_cpx(Addr ea) + INLINE static void op_cpx(Addr ea) { TRACE("CPX"); if (e || p.f_x) { - Byte data = mem.getByte(ea); + Byte data = getByte(ea); setnz_b(x.b - data); setc(x.b >= data); cycles += 2; } else { - Word data = mem.getWord(ea); + Word data = getWord(ea); setnz_w(x.w - data); setc(x.w >= data); cycles += 3; } } - INLINE void op_cpy(Addr ea) + INLINE static void op_cpy(Addr ea) { TRACE("CPY"); if (e || p.f_x) { - Byte data = mem.getByte(ea); + Byte data = getByte(ea); setnz_b(y.b - data); setc(y.b >= data); cycles += 2; } else { - Word data = mem.getWord(ea); + Word data = getWord(ea); setnz_w(y.w - data); setc(y.w >= data); cycles += 3; } } - INLINE void op_dec(Addr ea) + INLINE static void op_dec(Addr ea) { TRACE("DEC"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); - mem.setByte(ea, ++data); + setByte(ea, ++data); setnz_b(data); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); - mem.setWord(ea, ++data); + setWord(ea, ++data); setnz_w(data); cycles += 5; } } - INLINE void op_deca(Addr ea) + INLINE static void op_deca(Addr ea) { TRACE("DEC"); @@ -871,7 +870,7 @@ private: cycles += 2; } - INLINE void op_dex(Addr ea) + INLINE static void op_dex(Addr ea) { TRACE("DEX"); @@ -883,7 +882,7 @@ private: cycles += 2; } - INLINE void op_dey(Addr ea) + INLINE static void op_dey(Addr ea) { TRACE("DEY"); @@ -895,41 +894,41 @@ private: cycles += 2; } - INLINE void op_eor(Addr ea) + INLINE static void op_eor(Addr ea) { TRACE("EOR"); if (e || p.f_m) { - setnz_b(a.b ^= mem.getByte(ea)); + setnz_b(a.b ^= getByte(ea)); cycles += 2; } else { - setnz_w(a.w ^= mem.getWord(ea)); + setnz_w(a.w ^= getWord(ea)); cycles += 3; } } - INLINE void op_inc(Addr ea) + INLINE static void op_inc(Addr ea) { TRACE("INC"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); - mem.setByte(ea, ++data); + setByte(ea, ++data); setnz_b(data); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); - mem.setWord(ea, ++data); + setWord(ea, ++data); setnz_w(data); cycles += 5; } } - INLINE void op_inca(Addr ea) + INLINE static void op_inca(Addr ea) { TRACE("INC"); @@ -941,7 +940,7 @@ private: cycles += 2; } - INLINE void op_inx(Addr ea) + INLINE static void op_inx(Addr ea) { TRACE("INX"); @@ -953,7 +952,7 @@ private: cycles += 2; } - INLINE void op_iny(Addr ea) + INLINE static void op_iny(Addr ea) { TRACE("INY"); @@ -965,7 +964,7 @@ private: cycles += 2; } - INLINE void op_jmp(Addr ea) + INLINE static void op_jmp(Addr ea) { TRACE("JMP"); @@ -974,7 +973,7 @@ private: cycles += 1; } - INLINE void op_jsl(Addr ea) + INLINE static void op_jsl(Addr ea) { TRACE("JSL"); @@ -986,7 +985,7 @@ private: cycles += 5; } - INLINE void op_jsr(Addr ea) + INLINE static void op_jsr(Addr ea) { TRACE("JSR"); @@ -996,149 +995,149 @@ private: cycles += 4; } - INLINE void op_lda(Addr ea) + INLINE static void op_lda(Addr ea) { TRACE("LDA"); if (e || p.f_m) { - setnz_b(a.b = mem.getByte(ea)); + setnz_b(a.b = getByte(ea)); cycles += 2; } else { - setnz_w(a.w = mem.getWord(ea)); + setnz_w(a.w = getWord(ea)); cycles += 3; } } - INLINE void op_ldx(Addr ea) + INLINE static void op_ldx(Addr ea) { TRACE("LDX"); if (e || p.f_x) { - setnz_b(lo(x.w = mem.getByte(ea))); + setnz_b(lo(x.w = getByte(ea))); cycles += 2; } else { - setnz_w(x.w = mem.getWord(ea)); + setnz_w(x.w = getWord(ea)); cycles += 3; } } - INLINE void op_ldy(Addr ea) + INLINE static void op_ldy(Addr ea) { TRACE("LDY"); if (e || p.f_x) { - setnz_b(lo(y.w = mem.getByte(ea))); + setnz_b(lo(y.w = getByte(ea))); cycles += 2; } else { - setnz_w(y.w = mem.getWord(ea)); + setnz_w(y.w = getWord(ea)); cycles += 3; } } - INLINE void op_lsr(Addr ea) + INLINE static void op_lsr(Addr ea) { TRACE("LSR"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); setc(data & 0x01); setnz_b(data >>= 1); - mem.setByte(ea, data); + setByte(ea, data); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); setc(data & 0x0001); setnz_w(data >>= 1); - mem.setWord(ea, data); + setWord(ea, data); cycles += 5; } } - INLINE void op_lsra(Addr ea) + INLINE static 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); + setByte(ea, a.b); } else { setc(a.w & 0x0001); setnz_w(a.w >>= 1); - mem.setWord(ea, a.w); + setWord(ea, a.w); } cycles += 2; } - INLINE void op_mvn(Addr ea) + INLINE static void op_mvn(Addr ea) { TRACE("MVN"); - Byte src = mem.getByte(ea + 0); - Byte dst = mem.getByte(ea + 1); + Byte src = getByte(ea + 0); + Byte dst = getByte(ea + 1); - mem.setByte(join(dbr = dst, y.w++), mem.getByte(join(src, x.w++))); + setByte(join(dbr = dst, y.w++), getByte(join(src, x.w++))); if (--a.w != 0xffff) pc -= 3; cycles += 7; } - INLINE void op_mvp(Addr ea) + INLINE static void op_mvp(Addr ea) { TRACE("MVP"); - Byte src = mem.getByte(ea + 0); - Byte dst = mem.getByte(ea + 1); + Byte src = getByte(ea + 0); + Byte dst = getByte(ea + 1); - mem.setByte(join(dbr = dst, y.w--), mem.getByte(join(src, x.w--))); + setByte(join(dbr = dst, y.w--), getByte(join(src, x.w--))); if (--a.w != 0xffff) pc -= 3; cycles += 7; } - INLINE void op_nop(Addr ea) + INLINE static void op_nop(Addr ea) { TRACE("NOP"); cycles += 2; } - INLINE void op_ora(Addr ea) + INLINE static void op_ora(Addr ea) { TRACE("ORA"); if (e || p.f_m) { - setnz_b(a.b |= mem.getByte(ea)); + setnz_b(a.b |= getByte(ea)); cycles += 2; } else { - setnz_w(a.w |= mem.getWord(ea)); + setnz_w(a.w |= getWord(ea)); cycles += 3; } } - INLINE void op_pea(Addr ea) + INLINE static void op_pea(Addr ea) { TRACE("PEA"); - pushWord(mem.getWord(ea)); + pushWord(getWord(ea)); cycles += 5; } - INLINE void op_pei(Addr ea) + INLINE static void op_pei(Addr ea) { TRACE("PEI"); - pushWord(mem.getWord(ea)); + pushWord(getWord(ea)); cycles += 6; } - INLINE void op_per(Addr ea) + INLINE static void op_per(Addr ea) { TRACE("PER"); @@ -1146,7 +1145,7 @@ private: cycles += 6; } - INLINE void op_pha(Addr ea) + INLINE static void op_pha(Addr ea) { TRACE("PHA"); @@ -1160,7 +1159,7 @@ private: } } - INLINE void op_phb(Addr ea) + INLINE static void op_phb(Addr ea) { TRACE("PHB"); @@ -1168,7 +1167,7 @@ private: cycles += 3; } - INLINE void op_phd(Addr ea) + INLINE static void op_phd(Addr ea) { TRACE("PHD"); @@ -1176,7 +1175,7 @@ private: cycles += 4; } - INLINE void op_phk(Addr ea) + INLINE static void op_phk(Addr ea) { TRACE("PHK"); @@ -1184,7 +1183,7 @@ private: cycles += 3; } - INLINE void op_php(Addr ea) + INLINE static void op_php(Addr ea) { TRACE("PHP"); @@ -1192,7 +1191,7 @@ private: cycles += 3; } - INLINE void op_phx(Addr ea) + INLINE static void op_phx(Addr ea) { TRACE("PHX"); @@ -1206,7 +1205,7 @@ private: } } - INLINE void op_phy(Addr ea) + INLINE static void op_phy(Addr ea) { TRACE("PHY"); @@ -1220,7 +1219,7 @@ private: } } - INLINE void op_pla(Addr ea) + INLINE static void op_pla(Addr ea) { TRACE("PLA"); @@ -1234,7 +1233,7 @@ private: } } - INLINE void op_plb(Addr ea) + INLINE static void op_plb(Addr ea) { TRACE("PLB"); @@ -1242,7 +1241,7 @@ private: cycles += 4; } - INLINE void op_pld(Addr ea) + INLINE static void op_pld(Addr ea) { TRACE("PLD"); @@ -1250,7 +1249,7 @@ private: cycles += 5; } - INLINE void op_plk(Addr ea) + INLINE static void op_plk(Addr ea) { TRACE("PLK"); @@ -1258,7 +1257,7 @@ private: cycles += 4; } - INLINE void op_plp(Addr ea) + INLINE static void op_plp(Addr ea) { TRACE("PLP"); @@ -1275,7 +1274,7 @@ private: cycles += 4; } - INLINE void op_plx(Addr ea) + INLINE static void op_plx(Addr ea) { TRACE("PLX"); @@ -1289,7 +1288,7 @@ private: } } - INLINE void op_ply(Addr ea) + INLINE static void op_ply(Addr ea) { TRACE("PLY"); @@ -1303,40 +1302,40 @@ private: } } - INLINE void op_rep(Addr ea) + INLINE static void op_rep(Addr ea) { TRACE("REP"); - p.b &= ~mem.getByte(ea); + p.b &= ~getByte(ea); if (e) p.f_m = p.f_x = 1; cycles += 3; } - INLINE void op_rol(Addr ea) + INLINE static void op_rol(Addr ea) { TRACE("ROL"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); register Byte carry = p.f_c ? 0x01 : 0x00; setc(data & 0x80); setnz_b(data = (data << 1) | carry); - mem.setByte(ea, data); + setByte(ea, data); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); register Word carry = p.f_c ? 0x0001 : 0x0000; setc(data & 0x8000); setnz_w(data = (data << 1) | carry); - mem.setWord(ea, data); + setWord(ea, data); cycles += 5; } } - INLINE void op_rola(Addr ea) + INLINE static void op_rola(Addr ea) { TRACE("ROL"); @@ -1345,43 +1344,43 @@ private: setc(a.b & 0x80); setnz_b(a.b = (a.b << 1) | carry); - mem.setByte(ea, a.b); + 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); + setWord(ea, a.w); } cycles += 2; } - INLINE void op_ror(Addr ea) + INLINE static void op_ror(Addr ea) { TRACE("ROR"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); register Byte carry = p.f_c ? 0x80 : 0x00; setc(data & 0x80); setnz_b(data = (data >> 1) | carry); - mem.setByte(ea, data); + setByte(ea, data); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); register Word carry = p.f_c ? 0x8000 : 0x0000; setc(data & 0x8000); setnz_w(data = (data >> 1) | carry); - mem.setWord(ea, data); + setWord(ea, data); cycles += 5; } } - INLINE void op_rora(Addr ea) + INLINE static void op_rora(Addr ea) { TRACE("ROR"); @@ -1390,19 +1389,19 @@ private: setc(a.b & 0x80); setnz_b(a.b = (a.b >> 1) | carry); - mem.setByte(ea, a.b); + 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); + setWord(ea, a.w); } cycles += 2; } - INLINE void op_rti(Addr ea) + INLINE static void op_rti(Addr ea) { TRACE("RTI"); @@ -1420,7 +1419,7 @@ private: p.f_i = 0; } - INLINE void op_rtl(Addr ea) + INLINE static void op_rtl(Addr ea) { TRACE("RTL"); @@ -1429,7 +1428,7 @@ private: cycles += 6; } - INLINE void op_rts(Addr ea) + INLINE static void op_rts(Addr ea) { TRACE("RTS"); @@ -1437,12 +1436,12 @@ private: cycles += 6; } - INLINE void op_sbc(Addr ea) + INLINE static void op_sbc(Addr ea) { TRACE("SBC"); if (e || p.f_m) { - Byte data = ~mem.getByte(ea); + Byte data = ~getByte(ea); Word temp = a.b + data + p.f_c; setc(temp & 0x100); @@ -1451,7 +1450,7 @@ private: cycles += 2; } else { - Word data = ~mem.getWord(ea); + Word data = ~getWord(ea); int temp = a.w + data + p.f_c; setc(temp & 0x100); @@ -1461,7 +1460,7 @@ private: } } - INLINE void op_sec(Addr ea) + INLINE static void op_sec(Addr ea) { TRACE("SEC"); @@ -1469,7 +1468,7 @@ private: cycles += 2; } - INLINE void op_sed(Addr ea) + INLINE static void op_sed(Addr ea) { TRACE("SED"); @@ -1477,7 +1476,7 @@ private: cycles += 2; } - INLINE void op_sei(Addr ea) + INLINE static void op_sei(Addr ea) { TRACE("SEI"); @@ -1485,11 +1484,11 @@ private: cycles += 2; } - INLINE void op_sep(Addr ea) + INLINE static void op_sep(Addr ea) { TRACE("SEP"); - p.b |= mem.getByte(ea); + p.b |= getByte(ea); if (e) p.f_m = p.f_x = 1; if (p.f_x) { @@ -1499,21 +1498,21 @@ private: cycles += 3; } - INLINE void op_sta(Addr ea) + INLINE static void op_sta(Addr ea) { TRACE("STA"); if (e || p.f_m) { - mem.setByte(ea, a.b); + setByte(ea, a.b); cycles += 2; } else { - mem.setWord(ea, a.w); + setWord(ea, a.w); cycles += 3; } } - INLINE void op_stp(Addr ea) + INLINE static void op_stp(Addr ea) { TRACE("STP"); @@ -1526,49 +1525,49 @@ private: cycles += 3; } - INLINE void op_stx(Addr ea) + INLINE static void op_stx(Addr ea) { TRACE("STX"); if (e || p.f_x) { - mem.setByte(ea, x.b); + setByte(ea, x.b); cycles += 2; } else { - mem.setWord(ea, x.w); + setWord(ea, x.w); cycles += 3; } } - INLINE void op_sty(Addr ea) + INLINE static void op_sty(Addr ea) { TRACE("STY"); if (e || p.f_x) { - mem.setByte(ea, y.b); + setByte(ea, y.b); cycles += 2; } else { - mem.setWord(ea, y.w); + setWord(ea, y.w); cycles += 3; } } - INLINE void op_stz(Addr ea) + INLINE static void op_stz(Addr ea) { TRACE("STZ"); if (e || p.f_m) { - mem.setByte(ea, 0); + setByte(ea, 0); cycles += 2; } else { - mem.setWord(ea, 0); + setWord(ea, 0); cycles += 3; } } - INLINE void op_tax(Addr ea) + INLINE static void op_tax(Addr ea) { TRACE("TAX"); @@ -1580,7 +1579,7 @@ private: cycles += 2; } - INLINE void op_tay(Addr ea) + INLINE static void op_tay(Addr ea) { TRACE("TAY"); @@ -1592,7 +1591,7 @@ private: cycles += 2; } - INLINE void op_tcd(Addr ea) + INLINE static void op_tcd(Addr ea) { TRACE("TCD"); @@ -1600,7 +1599,7 @@ private: cycles += 2; } - INLINE void op_tdc(Addr ea) + INLINE static void op_tdc(Addr ea) { TRACE("TDC"); @@ -1612,7 +1611,7 @@ private: cycles += 2; } - INLINE void op_tcs(Addr ea) + INLINE static void op_tcs(Addr ea) { TRACE("TCS"); @@ -1620,47 +1619,47 @@ private: cycles += 2; } - INLINE void op_trb(Addr ea) + INLINE static void op_trb(Addr ea) { TRACE("TRB"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); - mem.setByte(ea, data & ~a.b); + setByte(ea, data & ~a.b); setz((a.b & data) == 0); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); - mem.setWord(ea, data & ~a.w); + setWord(ea, data & ~a.w); setz((a.w & data) == 0); cycles += 5; } } - INLINE void op_tsb(Addr ea) + INLINE static void op_tsb(Addr ea) { TRACE("TSB"); if (e || p.f_m) { - register Byte data = mem.getByte(ea); + register Byte data = getByte(ea); - mem.setByte(ea, data | a.b); + setByte(ea, data | a.b); setz((a.b & data) == 0); cycles += 4; } else { - register Word data = mem.getWord(ea); + register Word data = getWord(ea); - mem.setWord(ea, data | a.w); + setWord(ea, data | a.w); setz((a.w & data) == 0); cycles += 5; } } - INLINE void op_tsc(Addr ea) + INLINE static void op_tsc(Addr ea) { TRACE("TSC"); @@ -1672,7 +1671,7 @@ private: cycles += 2; } - INLINE void op_tsx(Addr ea) + INLINE static void op_tsx(Addr ea) { TRACE("TSX"); @@ -1684,7 +1683,7 @@ private: cycles += 2; } - INLINE void op_txa(Addr ea) + INLINE static void op_txa(Addr ea) { TRACE("TXA"); @@ -1696,7 +1695,7 @@ private: cycles += 2; } - INLINE void op_txs(Addr ea) + INLINE static void op_txs(Addr ea) { TRACE("TXS"); @@ -1708,7 +1707,7 @@ private: cycles += 2; } - INLINE void op_txy(Addr ea) + INLINE static void op_txy(Addr ea) { TRACE("TXY"); @@ -1720,7 +1719,7 @@ private: cycles += 2; } - INLINE void op_tya(Addr ea) + INLINE static void op_tya(Addr ea) { TRACE("TYA"); @@ -1732,7 +1731,7 @@ private: cycles += 2; } - INLINE void op_tyx(Addr ea) + INLINE static void op_tyx(Addr ea) { TRACE("TYX"); @@ -1744,7 +1743,7 @@ private: cycles += 2; } - INLINE void op_wai(Addr ea) + INLINE static void op_wai(Addr ea) { TRACE("WAI"); @@ -1757,17 +1756,17 @@ private: cycles += 3; } - INLINE void op_wdm(Addr ea) + INLINE static void op_wdm(Addr ea) { TRACE("WDM"); - switch (mem.getByte(ea)) { + switch (getByte(ea)) { case 0xff: stopped = true; break; } cycles += 3; } - INLINE void op_xba(Addr ea) + INLINE static void op_xba(Addr ea) { TRACE("XBA"); @@ -1776,7 +1775,7 @@ private: cycles += 3; } - INLINE void op_xce(Addr ea) + INLINE static void op_xce(Addr ea) { TRACE("XCE"); diff --git a/emu816.vcxproj b/emu816.vcxproj index c1f6d72..0032bb9 100644 --- a/emu816.vcxproj +++ b/emu816.vcxproj @@ -86,7 +86,7 @@ Level3 - Disabled + Custom WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -116,6 +116,7 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true Console diff --git a/emu816.vcxproj.user b/emu816.vcxproj.user index a0ff38b..8307d29 100644 --- a/emu816.vcxproj.user +++ b/emu816.vcxproj.user @@ -1,11 +1,11 @@  - -t examples/simple/simple.s28 + examples/simple/simple.s28 WindowsLocalDebugger - -t examples/simple/simple.s28 + examples/simple/simple.s28 WindowsLocalDebugger \ No newline at end of file diff --git a/examples/Dev65.jar b/examples/Dev65.jar index 4b52f76..36bc023 100644 Binary files a/examples/Dev65.jar and b/examples/Dev65.jar differ diff --git a/examples/simple/Makefile b/examples/simple/Makefile index f170429..40dcf92 100644 --- a/examples/simple/Makefile +++ b/examples/simple/Makefile @@ -26,7 +26,7 @@ OBJS = \ simple.obj -all: simple.s28 +all: simple.s28 simple.hex clean: $(RM) *.obj @@ -39,6 +39,10 @@ clean: simple.s28: $(OBJS) $(LK65) -bss $$0000-$$7FFF -code $$F000-$$FFFF -s28 -output $@ $(OBJS) + +simple.hex: $(OBJS) + $(LK65) -bss $$0000-$$7FFF -code $$F000-$$FFFF -hex -output $@ $(OBJS) + java -cp $(DEV65_JAR) uk.co.demon.obelisk.util.Hex2C < simple.hex > simple.txt #=============================================================================== # Dependencies diff --git a/examples/simple/simple.asm b/examples/simple/simple.asm index 14dfe23..ddfcd07 100644 --- a/examples/simple/simple.asm +++ b/examples/simple/simple.asm @@ -47,15 +47,16 @@ RESET: lda #STACK tcs - ldy #2 + ldy #100 repeat - ldx #123 + ldx #0 repeat dex until eq dey until eq - wdm #$ff + wdm #$ff + bra RESET ;=============================================================================== ; Dummy Interrupt Handlers diff --git a/examples/simple/simple.lst b/examples/simple/simple.lst index a29c3a1..0cc5926 100644 --- a/examples/simple/simple.lst +++ b/examples/simple/simple.lst @@ -168,18 +168,19 @@ Portable 65xx Assembler [16.06] 00:F006 A9???? : lda #STACK 00:F009 1B : tcs -00:F00A A00200 : ldy #2 +00:F00A A06400 : ldy #100 Portable 65xx Assembler [16.06] repeat -00:F00D A27B00 : ldx #123 +00:F00D A20000 : ldx #0 repeat 00:F010 CA : dex 00:F011 D0FD : until eq 00:F013 88 : dey 00:F014 D0F7 : until eq -00:F016 42FF : wdm #$ff +00:F016 42FF : wdm #$ff +00:F018 80E6 : bra RESET ;=============================================================================== ; Dummy Interrupt Handlers @@ -190,13 +191,13 @@ Portable 65xx Assembler [16.06] ABORTN: NMIN: BRKN -00:F018 80FE : bra $ +00:F01A 80FE : bra $ COP: ABORT: NMI: IRQBRK: -00:F01A 80FE : bra $ +00:F01C 80FE : bra $ ;=============================================================================== ; Vectors @@ -205,20 +206,20 @@ Portable 65xx Assembler [16.06] .org $ffe0 00:FFE0 00000000 : .space 4 ; Reserved -00:FFE4 18F0 : .word COPN ; $FFE4 - COP(816) -00:FFE6 18F0 : .word BRKN ; $FFE6 - BRK(816) -00:FFE8 18F0 : .word ABORTN ; $FFE8 - ABORT(816) -00:FFEA 18F0 : .word NMIN ; $FFEA - NMI(816) +00:FFE4 1AF0 : .word COPN ; $FFE4 - COP(816) +00:FFE6 1AF0 : .word BRKN ; $FFE6 - BRK(816) +00:FFE8 1AF0 : .word ABORTN ; $FFE8 - ABORT(816) +00:FFEA 1AF0 : .word NMIN ; $FFEA - NMI(816) 00:FFEC 0000 : .space 2 ; Reserved -00:FFEE 18F0 : .word IRQN ; $FFEE - IRQ(816) +00:FFEE 1AF0 : .word IRQN ; $FFEE - IRQ(816) 00:FFF0 00000000 : .space 4 -00:FFF4 1AF0 : .word COP ; $FFF4 - COP(C02) +00:FFF4 1CF0 : .word COP ; $FFF4 - COP(C02) 00:FFF6 0000 : .space 2 ; $Reserved -00:FFF8 1AF0 : .word ABORT ; $FFF8 - ABORT(C02) -00:FFFA 1AF0 : .word NMI ; $FFFA - NMI(C02) +00:FFF8 1CF0 : .word ABORT ; $FFF8 - ABORT(C02) +00:FFFA 1CF0 : .word NMI ; $FFFA - NMI(C02) 00:FFFC 00F0 : .word RESET ; $FFFC - RESET(C02) -00:FFFE 1AF0 : .word IRQBRK ; $FFFE - IRQBRK(C02) +00:FFFE 1CF0 : .word IRQBRK ; $FFFE - IRQBRK(C02) .end @@ -227,29 +228,29 @@ Portable 65xx Assembler [16.06] Symbol Table -ABORT 0000F01A | __6501__ 00000000 -ABORTN 0000F018 | __6502__ 00000000 -BRKN 0000F018 | __65832__ 00000000 +ABORT 0000F01C | __6501__ 00000000 +ABORTN 0000F01A | __6502__ 00000000 +BRKN 0000F01A | __65832__ 00000000 B_FLAG 00000010 | __65C02__ 00000000 -COP 0000F01A | __65SC02__ 00000000 -COPN 0000F018 | C_FLAG 00000001 +COP 0000F01C | __65SC02__ 00000000 +COPN 0000F01A | C_FLAG 00000001 C_FLAG 00000001 | __65816__ 00000001 D_FLAG 00000008 | Z_FLAG 00000002 -IRQBRK 0000F01A | I_FLAG 00000004 -IRQN 0000F018 | D_FLAG 00000008 +IRQBRK 0000F01C | I_FLAG 00000004 +IRQN 0000F01A | D_FLAG 00000008 I_FLAG 00000004 | B_FLAG 00000010 M_FLAG 00000020 | X_FLAG 00000010 -NMI 0000F01A | M_FLAG 00000020 -NMIN 0000F018 | V_FLAG 00000040 +NMI 0000F01C | M_FLAG 00000020 +NMIN 0000F01A | V_FLAG 00000040 N_FLAG 00000080 | N_FLAG 00000080 RESET 0000F000 | STACK 00000080' STACK 00000080' | RESET 0000F000 -V_FLAG 00000040 | ABORTN 0000F018 -X_FLAG 00000010 | BRKN 0000F018 -Z_FLAG 00000002 | COPN 0000F018 -__6501__ 00000000 | IRQN 0000F018 -__6502__ 00000000 | NMIN 0000F018 -__65816__ 00000001 | ABORT 0000F01A -__65832__ 00000000 | COP 0000F01A -__65C02__ 00000000 | IRQBRK 0000F01A -__65SC02__ 00000000 | NMI 0000F01A +V_FLAG 00000040 | ABORTN 0000F01A +X_FLAG 00000010 | BRKN 0000F01A +Z_FLAG 00000002 | COPN 0000F01A +__6501__ 00000000 | IRQN 0000F01A +__6502__ 00000000 | NMIN 0000F01A +__65816__ 00000001 | ABORT 0000F01C +__65832__ 00000000 | COP 0000F01C +__65C02__ 00000000 | IRQBRK 0000F01C +__65SC02__ 00000000 | NMI 0000F01C diff --git a/examples/simple/simple.map b/examples/simple/simple.map index 6fb2003..aba9480 100644 --- a/examples/simple/simple.map +++ b/examples/simple/simple.map @@ -5,5 +5,5 @@ Global Symbol Map Sections: .page0 : 00000000 - 0000007F in simple.obj -.code : 0000F000 - 0000F01B in simple.obj +.code : 0000F000 - 0000F01D in simple.obj 0000FFE0 - 0000FFFF in simple.obj diff --git a/examples/simple/simple.s28 b/examples/simple/simple.s28 index 0bcf3a5..d671dd8 100644 --- a/examples/simple/simple.s28 +++ b/examples/simple/simple.s28 @@ -1,4 +1,4 @@ -S22400F00078D818FBC230A980001BA00200A27B00CAD0FD88D0F742FF80FE80FE0000000070 +S22400F00078D818FBC230A980001BA06400A20000CAD0FD88D0F742FF80E680FE80FE000023 S22400F0200000000000000000000000000000000000000000000000000000000000000000CB S22400F0400000000000000000000000000000000000000000000000000000000000000000AB S22400F06000000000000000000000000000000000000000000000000000000000000000008B @@ -125,6 +125,6 @@ S22400FF6000000000000000000000000000000000000000000000000000000000000000007C S22400FF8000000000000000000000000000000000000000000000000000000000000000005C S22400FFA000000000000000000000000000000000000000000000000000000000000000003C S22400FFC000000000000000000000000000000000000000000000000000000000000000001C -S22400FFE00000000018F018F018F018F0000018F0000000001AF000001AF01AF000F01AF0BC +S22400FFE0000000001AF01AF01AF01AF000001AF0000000001CF000001CF01CF000F01CF0AA S505000000807A S80400F0000B diff --git a/mem816.cc b/mem816.cc index 1c30831..317d198 100644 --- a/mem816.cc +++ b/mem816.cc @@ -9,7 +9,7 @@ // // A Portable C++ WDC 65C816 Emulator //------------------------------------------------------------------------------ -// Copyright (C)2016 Andrew John Jacobs +// Copyright (C),2016 Andrew John Jacobs // All rights reserved. // // This work is made available under the terms of the Creative Commons @@ -21,22 +21,33 @@ #include "mem816.h" +mem816::Addr mem816::memMask; +mem816::Addr mem816::ramSize; + +mem816::Byte *mem816::pRAM; +const mem816::Byte *mem816::pROM; + //============================================================================== -// Construct a memory area using dynamic allocation -mem816::mem816(Addr memMask, Addr ramSize, const Byte *pROM) - : memMask(memMask), ramSize(ramSize), pROM(pROM), freeRAM(true) -{ - pRAM = new Byte[ramSize]; -} - -// Construct a memory area using statically allocated arrays -mem816::mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM) - : memMask(memMask), ramSize(ramSize), pRAM(pRAM), pROM(pROM), freeRAM(false) +// Never used. +mem816::mem816() { } -// Destory an instance releasing the RAM if allocated. +// Never used. mem816::~mem816() +{ } + +// Sets up the memory areas using a dynamically allocated array +void mem816::setMemory(Addr memMask, Addr ramSize, const Byte *pROM) { - if (freeRAM) delete pRAM; + setMemory(memMask, ramSize, new Byte[ramSize], pROM); +} + +// Sets up the memory area using pre-allocated array +void mem816::setMemory(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM) +{ + mem816::memMask = memMask; + mem816::ramSize = ramSize; + mem816::pRAM = pRAM; + mem816::pROM = pROM; } \ No newline at end of file diff --git a/mem816.h b/mem816.h index 3909db5..ea83ac5 100644 --- a/mem816.h +++ b/mem816.h @@ -9,7 +9,7 @@ // // A Portable C++ WDC 65C816 Emulator //------------------------------------------------------------------------------ -// Copyright (C)2016 Andrew John Jacobs +// Copyright (C),2016 Andrew John Jacobs // All rights reserved. // // This work is made available under the terms of the Creative Commons @@ -24,15 +24,19 @@ #include "wdc816.h" +// The mem816 class defines a set of standard methods for defining and accessing +// the emulated memory area. + class mem816 : public wdc816 { public: - mem816(Addr memMask, Addr ramSize, const Byte *pROM); - mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM); - ~mem816(); + // Define the memory areas and sizes + static void setMemory (Addr memMask, Addr ramSize, const Byte *pROM); + static void setMemory (Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM); - INLINE Byte getByte(Addr ea) + // Fetch a byte from memory + INLINE static Byte getByte(Addr ea) { if ((ea &= memMask) < ramSize) return (pRAM[ea]); @@ -40,35 +44,41 @@ public: return (pROM[ea - ramSize]); } - INLINE Word getWord(Addr ea) + // Fetch a word from memory + INLINE static Word getWord(Addr ea) { - return (join(getByte(ea + 0), getByte(ea + 1))); + return (join(getByte(ea + 0), getByte(ea + 1))); } - INLINE Addr getAddr(Addr ea) + // Fetch a long address from memory + INLINE static Addr getAddr(Addr ea) { return (join(getByte(ea + 2), getWord(ea + 0))); } - INLINE void setByte(Addr ea, Byte data) + // Write a byte to memory + INLINE static void setByte(Addr ea, Byte data) { if ((ea &= memMask) < ramSize) pRAM[ea] = data; } - INLINE void setWord(Addr ea, Word data) + // Write a word to memory + INLINE static void setWord(Addr ea, Word data) { - setByte(ea + 0, lo(data)); - setByte(ea + 1, hi(data)); + setByte(ea + 0, lo(data)); + setByte(ea + 1, hi(data)); } +protected: + mem816(); + ~mem816(); + private: - const Addr memMask; - const Addr ramSize; + static Addr memMask; // The address mask pattern + static Addr ramSize; // The amount of RAM - Byte *pRAM; - const Byte *pROM; - - const bool freeRAM; + static Byte *pRAM; // Base of RAM memory array + static const Byte *pROM; // Base of ROM memory array }; -#endif +#endif \ No newline at end of file diff --git a/program.cc b/program.cc index e1f7981..10cd9c2 100644 --- a/program.cc +++ b/program.cc @@ -40,23 +40,20 @@ using namespace std; #define RAM_SIZE (512 * 1024) #define MEM_MASK (512 * 1024L - 1) -mem816 mem(MEM_MASK, RAM_SIZE, NULL); -emu816 emu(mem); - bool trace = false; //============================================================================== // Initialise the emulator -void setup() +INLINE void setup() { - emu.reset(trace); + emu816::setMemory(MEM_MASK, RAM_SIZE, NULL); } // Execute instructions -void loop() +INLINE void loop() { - emu.step(); + emu816::step(); } //============================================================================== @@ -108,7 +105,7 @@ void load(char *filename) unsigned long addr = toAddr(line, offset); count -= 4; while (count-- > 0) { - mem.setByte(addr++, toByte(line, offset)); + emu816::setByte(addr++, toByte(line, offset)); } } } @@ -123,6 +120,8 @@ int main(int argc, char **argv) { int index = 1; + setup(); + while (index < argc) { if (argv[index][0] != '-') break; @@ -155,16 +154,17 @@ int main(int argc, char **argv) QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&start); - setup(); - while (!emu.isStopped ()) + emu816::reset(trace); + while (!emu816::isStopped ()) loop(); QueryPerformanceCounter(&end); double secs = (end.QuadPart - start.QuadPart) / (double) freq.QuadPart; - double speed = emu.getCycles() / secs; + double speed = emu816::getCycles() / secs; + cout << endl << "Executed " << emu816::getCycles() << " in " << secs << " Secs"; cout << endl << "Overall CPU Frequency = "; if (speed < 1000.0) cout << speed << " Hz"; @@ -176,5 +176,6 @@ int main(int argc, char **argv) } cout << endl; + system("pause"); return(0); } diff --git a/wdc816.cc b/wdc816.cc index 3a0b388..2aac9cc 100644 --- a/wdc816.cc +++ b/wdc816.cc @@ -9,7 +9,7 @@ // // A Portable C++ WDC 65C816 Emulator //------------------------------------------------------------------------------ -// Copyright (C)2016 Andrew John Jacobs +// Copyright (C),2016 Andrew John Jacobs // All rights reserved. // // This work is made available under the terms of the Creative Commons @@ -21,9 +21,11 @@ #include "wdc816.h" +// Never used. wdc816::wdc816() { } +// Never used. wdc816::~wdc816() { } diff --git a/wdc816.h b/wdc816.h index 405ec15..04d7f61 100644 --- a/wdc816.h +++ b/wdc816.h @@ -9,7 +9,7 @@ // // A Portable C++ WDC 65C816 Emulator //------------------------------------------------------------------------------ -// Copyright (C)2016 Andrew John Jacobs +// Copyright (C),2016 Andrew John Jacobs // All rights reserved. // // This work is made available under the terms of the Creative Commons @@ -22,25 +22,23 @@ #ifndef WDC816_H #define WDC816_H -//#define CHIPKIT - #ifdef CHIPKIT # define INLINE inline #else # define INLINE inline #endif +// The wdc816 class defines common types for 8-, 16- and 24-bit data values and +// a set of common functions for manipulating them. + 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(); + typedef unsigned char Bit; + typedef unsigned char Byte; + typedef unsigned short Word; + typedef unsigned long Addr; // Convert a value to a hex string. static char *toHex(unsigned long value, unsigned int digits); @@ -80,5 +78,9 @@ public: { return ((value >> 8) | (value << 8)); } + +protected: + wdc816(); + ~wdc816(); }; #endif \ No newline at end of file