Merge branch 'master' of https://github.com/MoleskiCoder/EightBit into master

This commit is contained in:
Adrian Conlon 2021-05-29 10:31:47 +01:00
commit 502c554e84
25 changed files with 460 additions and 302 deletions

View File

@ -3,19 +3,20 @@
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <memory> #include <memory>
#include <stdexcept>
#include <string> #include <string>
#include <SDL.h> #include <SDL.h>
#include <Device.h> #include <Device.h>
#include "GameController.h"
#include "SDLWrapper.h" #include "SDLWrapper.h"
class Configuration; class Configuration;
namespace Gaming { namespace Gaming {
class GameController;
class Game : public EightBit::Device { class Game : public EightBit::Device {
public: public:
Game(); Game();
@ -28,10 +29,10 @@ namespace Gaming {
virtual float fps() const = 0; virtual float fps() const = 0;
virtual bool useVsync() const = 0; virtual bool useVsync() const = 0;
virtual int windowWidth() const noexcept { return displayWidth() * displayScale(); } virtual int windowWidth() const noexcept;
virtual int windowHeight() const noexcept { return displayHeight() * displayScale(); } virtual int windowHeight() const noexcept;
virtual int displayWidth() const noexcept { return rasterWidth(); } virtual int displayWidth() const noexcept;
virtual int displayHeight() const noexcept { return rasterHeight(); } virtual int displayHeight() const noexcept;
virtual int displayScale() const noexcept = 0; virtual int displayScale() const noexcept = 0;
virtual int rasterWidth() const noexcept = 0; virtual int rasterWidth() const noexcept = 0;
virtual int rasterHeight() const noexcept = 0; virtual int rasterHeight() const noexcept = 0;
@ -67,19 +68,8 @@ namespace Gaming {
void toggleFullscreen(); void toggleFullscreen();
std::shared_ptr<GameController> gameController(const int which) const { std::shared_ptr<GameController> gameController(int which) const;
const auto i = m_gameControllers.find(which); int mappedController(const SDL_JoystickID which) const;
if (i == m_gameControllers.cend())
throw std::runtime_error("Unknown controller");
return i->second;
}
int mappedController(const SDL_JoystickID which) const {
const auto i = m_mappedControllers.find(which);
if (i == m_mappedControllers.cend())
throw std::runtime_error("Unknown joystick");
return i->second;
}
int chooseControllerIndex(int who) const; int chooseControllerIndex(int who) const;
std::shared_ptr<GameController> chooseController(int who) const; std::shared_ptr<GameController> chooseController(int who) const;

View File

@ -1,5 +1,8 @@
#pragma once #pragma once
#include <string>
#include <stdexcept>
namespace Gaming { namespace Gaming {
class SDLWrapper final { class SDLWrapper final {
public: public:

View File

@ -1,12 +1,30 @@
#include "stdafx.h" #include "stdafx.h"
#include "Game.h" #include "Game.h"
#include "GameController.h"
namespace Gaming { namespace Gaming {
Game::Game() {} Game::Game() {}
Game::~Game() {} Game::~Game() {}
int Game::windowWidth() const noexcept {
return displayWidth() * displayScale();
}
int Game::windowHeight() const noexcept {
return displayHeight() * displayScale();
}
int Game::displayWidth() const noexcept {
return rasterWidth();
}
int Game::displayHeight() const noexcept {
return rasterHeight();
}
void Game::raisePOWER() { void Game::raisePOWER() {
Device::raisePOWER(); Device::raisePOWER();
@ -168,6 +186,20 @@ void Game::addJoystick(SDL_Event& e) {
SDL_Log("Joystick device %d added (%zd controllers)", which, m_gameControllers.size()); SDL_Log("Joystick device %d added (%zd controllers)", which, m_gameControllers.size());
} }
std::shared_ptr<GameController> Game::gameController(const int which) const {
const auto i = m_gameControllers.find(which);
if (i == m_gameControllers.cend())
throw std::runtime_error("Unknown controller");
return i->second;
}
int Game::mappedController(const SDL_JoystickID which) const {
const auto i = m_mappedControllers.find(which);
if (i == m_mappedControllers.cend())
throw std::runtime_error("Unknown joystick");
return i->second;
}
// -1 if no controllers, otherwise index // -1 if no controllers, otherwise index
int Game::chooseControllerIndex(const int who) const { int Game::chooseControllerIndex(const int who) const {
const auto count = m_gameControllers.size(); const auto count = m_gameControllers.size();

View File

@ -40,7 +40,7 @@ namespace EightBit {
Signal<EventArgs> MachineTicked; Signal<EventArgs> MachineTicked;
void tickMachine(const int extra) { for (int i = 0; i < extra; ++i) tickMachine(); } void tickMachine(const int extra) { for (int i = 0; i < extra; ++i) tickMachine(); }
void tickMachine() { tick(4); MachineTicked.fire(EventArgs::empty()); } void tickMachine() { tick(4); MachineTicked.fire(); }
protected: protected:
int execute() final; int execute() final;

View File

@ -32,15 +32,15 @@ namespace EightBit {
Signal<MOS6502> ExecutedInstruction; Signal<MOS6502> ExecutedInstruction;
int execute() final; int execute() final;
int step() final; [[nodiscard]] int step() final;
auto& X() { return x; } [[nodiscard]] auto& X() { return x; }
auto& Y() { return y; } [[nodiscard]] auto& Y() { return y; }
auto& A() { return a; } [[nodiscard]] auto& A() { return a; }
auto& S() { return s; } [[nodiscard]] auto& S() { return s; }
auto& P() { return p; } [[nodiscard]] auto& P() { return p; }
const auto& P() const { return p; } [[nodiscard]] const auto& P() const { return p; }
DECLARE_PIN_INPUT(NMI) DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_INPUT(SO) DECLARE_PIN_INPUT(SO)
@ -49,21 +49,21 @@ namespace EightBit {
DECLARE_PIN_OUTPUT(RW) DECLARE_PIN_OUTPUT(RW)
protected: protected:
virtual void handleRESET() final; void handleRESET() final;
virtual void handleINT() final; void handleINT() final;
virtual void busWrite() final; void busWrite() final;
virtual uint8_t busRead() final; [[nodiscard]] uint8_t busRead() final;
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0); [[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0);
uint8_t sbc(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data);
uint8_t sub_b(uint8_t operand, uint8_t data, int borrow); [[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow);
uint8_t sub_d(uint8_t operand, uint8_t data, int borrow); [[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow);
virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0); [[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0);
uint8_t adc(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data);
uint8_t add_b(uint8_t operand, uint8_t data, int carry); [[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry);
uint8_t add_d(uint8_t operand, uint8_t data, int carry); [[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry);
private: private:
const uint8_t IRQvector = 0xfe; // IRQ vector const uint8_t IRQvector = 0xfe; // IRQ vector
@ -75,25 +75,25 @@ namespace EightBit {
void interrupt(); void interrupt();
virtual void push(uint8_t value) final; void push(uint8_t value) final;
virtual uint8_t pop() final; [[nodiscard]] uint8_t pop() final;
// Dummy stack push, used during RESET // Dummy stack push, used during RESET
void dummyPush(uint8_t value); void dummyPush(uint8_t value);
// Addressing modes // Addressing modes
register16_t Address_Absolute(); [[nodiscard]] register16_t Address_Absolute();
uint8_t Address_ZeroPage(); [[nodiscard]] uint8_t Address_ZeroPage();
register16_t Address_ZeroPageIndirect(); [[nodiscard]] register16_t Address_ZeroPageIndirect();
register16_t Address_Indirect(); [[nodiscard]] register16_t Address_Indirect();
uint8_t Address_ZeroPageX(); [[nodiscard]] uint8_t Address_ZeroPageX();
uint8_t Address_ZeroPageY(); [[nodiscard]] uint8_t Address_ZeroPageY();
std::pair<register16_t, uint8_t> Address_AbsoluteX(); [[nodiscard]] std::pair<register16_t, uint8_t> Address_AbsoluteX();
std::pair<register16_t, uint8_t> Address_AbsoluteY(); [[nodiscard]] std::pair<register16_t, uint8_t> Address_AbsoluteY();
register16_t Address_IndexedIndirectX(); [[nodiscard]] register16_t Address_IndexedIndirectX();
std::pair<register16_t, uint8_t> Address_IndirectIndexedY(); [[nodiscard]] std::pair<register16_t, uint8_t> Address_IndirectIndexedY();
register16_t Address_relative_byte(); [[nodiscard]] register16_t Address_relative_byte();
// Addressing modes, read // Addressing modes, read
@ -121,19 +121,19 @@ namespace EightBit {
// Flag checking // Flag checking
auto interruptMasked() const { return P() & IF; } [[nodiscard]] auto interruptMasked() const { return P() & IF; }
auto decimal() const { return P() & DF; } [[nodiscard]] auto decimal() const { return P() & DF; }
auto negative() const { return P() & NF; } [[nodiscard]] auto negative() const { return P() & NF; }
auto zero() const { return P() & ZF; } [[nodiscard]] auto zero() const { return P() & ZF; }
auto overflow() const { return P() & VF; } [[nodiscard]] auto overflow() const { return P() & VF; }
auto carry() const { return P() & CF; } [[nodiscard]] auto carry() const { return P() & CF; }
// Miscellaneous // Miscellaneous
void branch(int condition); void branch(int condition);
auto through(const uint8_t data) { [[nodiscard]] auto through(const uint8_t data) {
adjustNZ(data); adjustNZ(data);
return data; return data;
} }
@ -146,20 +146,20 @@ namespace EightBit {
// Instruction implementations // Instruction implementations
uint8_t andr(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data);
uint8_t asl(uint8_t value); [[nodiscard]] uint8_t asl(uint8_t value);
void bit(uint8_t operand, uint8_t data); void bit(uint8_t operand, uint8_t data);
void cmp(uint8_t first, uint8_t second); void cmp(uint8_t first, uint8_t second);
uint8_t dec(uint8_t value); [[nodiscard]] uint8_t dec(uint8_t value);
uint8_t eorr(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data);
uint8_t inc(uint8_t value); [[nodiscard]] uint8_t inc(uint8_t value);
void jsr(); void jsr();
uint8_t lsr(uint8_t value); [[nodiscard]] uint8_t lsr(uint8_t value);
uint8_t orr(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data);
void php(); void php();
void plp(); void plp();
uint8_t rol(uint8_t operand); [[nodiscard]] uint8_t rol(uint8_t operand);
uint8_t ror(uint8_t operand); [[nodiscard]] uint8_t ror(uint8_t operand);
void rti(); void rti();
void rts(); void rts();

View File

@ -17,15 +17,15 @@ EightBit::Profiler::Profiler(MOS6502& targetProcessor, Disassembly& disassembler
} }
void EightBit::Profiler::Generate() { void EightBit::Profiler::Generate() {
StartingOutput.fire(EventArgs::empty()); StartingOutput.fire();
EmitProfileInformation(); EmitProfileInformation();
StartingOutput.fire(EventArgs::empty()); StartingOutput.fire();
} }
void EightBit::Profiler::EmitProfileInformation() { void EightBit::Profiler::EmitProfileInformation() {
{ {
StartingLineOutput.fire(EventArgs::empty()); StartingLineOutput.fire();
// For each memory address // For each memory address
for (int address = 0; address < 0x10000; ++address) { for (int address = 0; address < 0x10000; ++address) {
// If there are any cycles associated // If there are any cycles associated
@ -37,11 +37,11 @@ void EightBit::Profiler::EmitProfileInformation() {
EmitLine.fire(event); EmitLine.fire(event);
} }
} }
FinishedLineOutput.fire(EventArgs::empty()); FinishedLineOutput.fire();
} }
{ {
StartingScopeOutput.fire(EventArgs::empty()); StartingScopeOutput.fire();
for (auto& scopeCycle : scopeCycles) { for (auto& scopeCycle : scopeCycles) {
auto name = scopeCycle.first; auto name = scopeCycle.first;
auto cycles = scopeCycle.second; auto cycles = scopeCycle.second;
@ -50,7 +50,7 @@ void EightBit::Profiler::EmitProfileInformation() {
ProfileScopeEventArgs event(name, cycles, count); ProfileScopeEventArgs event(name, cycles, count);
EmitScope.fire(event); EmitScope.fire(event);
} }
FinishedScopeOutput.fire(EventArgs::empty()); FinishedScopeOutput.fire();
} }
} }

View File

@ -120,45 +120,45 @@ int EightBit::MOS6502::execute() {
case 0x05: A() = orr(A(), AM_ZeroPage()); break; // ORA (zero page) case 0x05: A() = orr(A(), AM_ZeroPage()); break; // ORA (zero page)
case 0x06: memoryReadModifyWrite(asl(AM_ZeroPage())); break; // ASL (zero page) case 0x06: memoryReadModifyWrite(asl(AM_ZeroPage())); break; // ASL (zero page)
case 0x07: slo(AM_ZeroPage()); break; // *SLO (zero page) case 0x07: slo(AM_ZeroPage()); break; // *SLO (zero page)
case 0x08: memoryRead(); php(); break; // PHP (implied) case 0x08: memoryRead(); php(); break; // PHP (implied)
case 0x09: A() = orr(A(), AM_Immediate()); break; // ORA (immediate) case 0x09: A() = orr(A(), AM_Immediate()); break; // ORA (immediate)
case 0x0a: memoryRead(); A() = asl(A()); break; // ASL A (implied) case 0x0a: memoryRead(); A() = asl(A()); break; // ASL A (implied)
case 0x0b: anc(AM_Immediate()); break; // *ANC (immediate) case 0x0b: anc(AM_Immediate()); break; // *ANC (immediate)
case 0x0c: AM_Absolute(); break; // *NOP (absolute) case 0x0c: AM_Absolute(); break; // *NOP (absolute)
case 0x0d: A() = orr(A(), AM_Absolute()); break; // ORA (absolute) case 0x0d: A() = orr(A(), AM_Absolute()); break; // ORA (absolute)
case 0x0e: memoryReadModifyWrite(asl(AM_Absolute())); break; // ASL (absolute) case 0x0e: memoryReadModifyWrite(asl(AM_Absolute())); break; // ASL (absolute)
case 0x0f: slo(AM_Absolute()); break; // *SLO (absolute) case 0x0f: slo(AM_Absolute()); break; // *SLO (absolute)
case 0x10: branch(!negative()); break; // BPL (relative) case 0x10: branch(!negative()); break; // BPL (relative)
case 0x11: A() = orr(A(), AM_IndirectIndexedY()); break; // ORA (indirect indexed Y) case 0x11: A() = orr(A(), AM_IndirectIndexedY()); break; // ORA (indirect indexed Y)
case 0x12: break; case 0x12: break;
case 0x13: slo(AM_IndirectIndexedY()); break; // *SLO (indirect indexed Y) case 0x13: slo(AM_IndirectIndexedY()); break; // *SLO (indirect indexed Y)
case 0x14: AM_ZeroPageX(); break; // *NOP (zero page, X) case 0x14: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x15: A() = orr(A(), AM_ZeroPageX()); break; // ORA (zero page, X) case 0x15: A() = orr(A(), AM_ZeroPageX()); break; // ORA (zero page, X)
case 0x16: memoryReadModifyWrite(asl(AM_ZeroPageX())); break; // ASL (zero page, X) case 0x16: memoryReadModifyWrite(asl(AM_ZeroPageX())); break; // ASL (zero page, X)
case 0x17: slo(AM_ZeroPageX()); break; // *SLO (zero page, X) case 0x17: slo(AM_ZeroPageX()); break; // *SLO (zero page, X)
case 0x18: memoryRead(); P() = clearBit(P(), CF); break; // CLC (implied) case 0x18: memoryRead(); P() = clearBit(P(), CF); break; // CLC (implied)
case 0x19: A() = orr(A(), AM_AbsoluteY()); break; // ORA (absolute, Y) case 0x19: A() = orr(A(), AM_AbsoluteY()); break; // ORA (absolute, Y)
case 0x1a: memoryRead(); break; // *NOP (implied) case 0x1a: memoryRead(); break; // *NOP (implied)
case 0x1b: slo(AM_AbsoluteY()); break; // *SLO (absolute, Y) case 0x1b: slo(AM_AbsoluteY()); break; // *SLO (absolute, Y)
case 0x1c: AM_AbsoluteX(); break; // *NOP (absolute, X) case 0x1c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x1d: A() = orr(A(), AM_AbsoluteX()); break; // ORA (absolute, X) case 0x1d: A() = orr(A(), AM_AbsoluteX()); break; // ORA (absolute, X)
case 0x1e: memoryReadModifyWrite(asl(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ASL (absolute, X) case 0x1e: memoryReadModifyWrite(asl(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ASL (absolute, X)
case 0x1f: slo(AM_AbsoluteX()); break; // *SLO (absolute, X) case 0x1f: slo(AM_AbsoluteX()); break; // *SLO (absolute, X)
case 0x20: jsr(); break; // JSR (absolute) case 0x20: jsr(); break; // JSR (absolute)
case 0x21: A() = andr(A(), AM_IndexedIndirectX()); break; // AND (indexed indirect X) case 0x21: A() = andr(A(), AM_IndexedIndirectX()); break; // AND (indexed indirect X)
case 0x22: break; case 0x22: break;
case 0x23: rla(AM_IndexedIndirectX()); break; // *RLA (indexed indirect X) case 0x23: rla(AM_IndexedIndirectX()); break; // *RLA (indexed indirect X)
case 0x24: bit(A(), AM_ZeroPage()); break; // BIT (zero page) case 0x24: bit(A(), AM_ZeroPage()); break; // BIT (zero page)
case 0x25: A() = andr(A(), AM_ZeroPage()); break; // AND (zero page) case 0x25: A() = andr(A(), AM_ZeroPage()); break; // AND (zero page)
case 0x26: memoryReadModifyWrite(rol(AM_ZeroPage())); break; // ROL (zero page) case 0x26: memoryReadModifyWrite(rol(AM_ZeroPage())); break; // ROL (zero page)
case 0x27: rla(AM_ZeroPage()); break; // *RLA (zero page) case 0x27: rla(AM_ZeroPage()); break; // *RLA (zero page)
case 0x28: memoryRead(); getBytePaged(1, S()); plp(); break; // PLP (implied) case 0x28: memoryRead(); getBytePaged(1, S()); plp(); break; // PLP (implied)
case 0x29: A() = andr(A(), AM_Immediate()); break; // AND (immediate) case 0x29: A() = andr(A(), AM_Immediate()); break; // AND (immediate)
case 0x2a: memoryRead(); A() = rol(A()); break; // ROL A (implied) case 0x2a: memoryRead(); A() = rol(A()); break; // ROL A (implied)
case 0x2b: anc(AM_Immediate()); break; // *ANC (immediate) case 0x2b: anc(AM_Immediate()); break; // *ANC (immediate)
case 0x2c: bit(A(), AM_Absolute()); break; // BIT (absolute) case 0x2c: bit(A(), AM_Absolute()); break; // BIT (absolute)
case 0x2d: A() = andr(A(), AM_Absolute()); break; // AND (absolute) case 0x2d: A() = andr(A(), AM_Absolute()); break; // AND (absolute)
case 0x2e: memoryReadModifyWrite(rol(AM_Absolute())); break; // ROL (absolute) case 0x2e: memoryReadModifyWrite(rol(AM_Absolute())); break; // ROL (absolute)
case 0x2f: rla(AM_Absolute()); break; // *RLA (absolute) case 0x2f: rla(AM_Absolute()); break; // *RLA (absolute)
@ -168,19 +168,19 @@ int EightBit::MOS6502::execute() {
case 0x32: break; case 0x32: break;
case 0x33: rla(AM_IndirectIndexedY()); break; // *RLA (indirect indexed Y) case 0x33: rla(AM_IndirectIndexedY()); break; // *RLA (indirect indexed Y)
case 0x34: AM_ZeroPageX(); break; // *NOP (zero page, X) case 0x34: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x35: A() = andr(A(), AM_ZeroPageX()); break; // AND (zero page, X) case 0x35: A() = andr(A(), AM_ZeroPageX()); break; // AND (zero page, X)
case 0x36: memoryReadModifyWrite(rol(AM_ZeroPageX())); break; // ROL (zero page, X) case 0x36: memoryReadModifyWrite(rol(AM_ZeroPageX())); break; // ROL (zero page, X)
case 0x37: rla(AM_ZeroPageX()); break; // *RLA (zero page, X) case 0x37: rla(AM_ZeroPageX()); break; // *RLA (zero page, X)
case 0x38: memoryRead(); P() = setBit(P(), CF); break; // SEC (implied) case 0x38: memoryRead(); P() = setBit(P(), CF); break; // SEC (implied)
case 0x39: A() = andr(A(), AM_AbsoluteY()); break; // AND (absolute, Y) case 0x39: A() = andr(A(), AM_AbsoluteY()); break; // AND (absolute, Y)
case 0x3a: memoryRead(); break; // *NOP (implied) case 0x3a: memoryRead(); break; // *NOP (implied)
case 0x3b: rla(AM_AbsoluteY()); break; // *RLA (absolute, Y) case 0x3b: rla(AM_AbsoluteY()); break; // *RLA (absolute, Y)
case 0x3c: AM_AbsoluteX(); break; // *NOP (absolute, X) case 0x3c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x3d: A() = andr(A(), AM_AbsoluteX()); break; // AND (absolute, X) case 0x3d: A() = andr(A(), AM_AbsoluteX()); break; // AND (absolute, X)
case 0x3e: memoryReadModifyWrite(rol(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ROL (absolute, X) case 0x3e: memoryReadModifyWrite(rol(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ROL (absolute, X)
case 0x3f: rla(AM_AbsoluteX()); break; // *RLA (absolute, X) case 0x3f: rla(AM_AbsoluteX()); break; // *RLA (absolute, X)
case 0x40: memoryRead(); rti(); break; // RTI (implied) case 0x40: memoryRead(); rti(); break; // RTI (implied)
case 0x41: A() = eorr(A(), AM_IndexedIndirectX()); break; // EOR (indexed indirect X) case 0x41: A() = eorr(A(), AM_IndexedIndirectX()); break; // EOR (indexed indirect X)
case 0x42: break; case 0x42: break;
case 0x43: sre(AM_IndexedIndirectX()); break; // *SRE (indexed indirect X) case 0x43: sre(AM_IndexedIndirectX()); break; // *SRE (indexed indirect X)
@ -188,33 +188,33 @@ int EightBit::MOS6502::execute() {
case 0x45: A() = eorr(A(), AM_ZeroPage()); break; // EOR (zero page) case 0x45: A() = eorr(A(), AM_ZeroPage()); break; // EOR (zero page)
case 0x46: memoryReadModifyWrite(lsr(AM_ZeroPage())); break; // LSR (zero page) case 0x46: memoryReadModifyWrite(lsr(AM_ZeroPage())); break; // LSR (zero page)
case 0x47: sre(AM_ZeroPage()); break; // *SRE (zero page) case 0x47: sre(AM_ZeroPage()); break; // *SRE (zero page)
case 0x48: memoryRead(); push(A()); break; // PHA (implied) case 0x48: memoryRead(); push(A()); break; // PHA (implied)
case 0x49: A() = eorr(A(), AM_Immediate()); break; // EOR (immediate) case 0x49: A() = eorr(A(), AM_Immediate()); break; // EOR (immediate)
case 0x4a: memoryRead(); A() = lsr(A()); break; // LSR A (implied) case 0x4a: memoryRead(); A() = lsr(A()); break; // LSR A (implied)
case 0x4b: asr(AM_Immediate()); break; // *ASR (immediate) case 0x4b: asr(AM_Immediate()); break; // *ASR (immediate)
case 0x4c: jump(Address_Absolute()); break; // JMP (absolute) case 0x4c: jump(Address_Absolute()); break; // JMP (absolute)
case 0x4d: A() = eorr(A(), AM_Absolute()); break; // EOR (absolute) case 0x4d: A() = eorr(A(), AM_Absolute()); break; // EOR (absolute)
case 0x4e: memoryReadModifyWrite(lsr(AM_Absolute())); break; // LSR (absolute) case 0x4e: memoryReadModifyWrite(lsr(AM_Absolute())); break; // LSR (absolute)
case 0x4f: sre(AM_Absolute()); break; // *SRE (absolute) case 0x4f: sre(AM_Absolute()); break; // *SRE (absolute)
case 0x50: branch(!overflow()); break; // BVC (relative) case 0x50: branch(!overflow()); break; // BVC (relative)
case 0x51: A() = eorr(A(), AM_IndirectIndexedY()); break; // EOR (indirect indexed Y) case 0x51: A() = eorr(A(), AM_IndirectIndexedY()); break; // EOR (indirect indexed Y)
case 0x52: break; case 0x52: break;
case 0x53: sre(AM_IndirectIndexedY()); break; // *SRE (indirect indexed Y) case 0x53: sre(AM_IndirectIndexedY()); break; // *SRE (indirect indexed Y)
case 0x54: AM_ZeroPageX(); break; // *NOP (zero page, X) case 0x54: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x55: A() = eorr(A(), AM_ZeroPageX()); break; // EOR (zero page, X) case 0x55: A() = eorr(A(), AM_ZeroPageX()); break; // EOR (zero page, X)
case 0x56: memoryReadModifyWrite(lsr(AM_ZeroPageX())); break; // LSR (zero page, X) case 0x56: memoryReadModifyWrite(lsr(AM_ZeroPageX())); break; // LSR (zero page, X)
case 0x57: sre(AM_ZeroPageX()); break; // *SRE (zero page, X) case 0x57: sre(AM_ZeroPageX()); break; // *SRE (zero page, X)
case 0x58: memoryRead(); P() = clearBit(P(), IF); break; // CLI (implied) case 0x58: memoryRead(); P() = clearBit(P(), IF); break; // CLI (implied)
case 0x59: A() = eorr(A(), AM_AbsoluteY()); break; // EOR (absolute, Y) case 0x59: A() = eorr(A(), AM_AbsoluteY()); break; // EOR (absolute, Y)
case 0x5a: memoryRead(); break; // *NOP (implied) case 0x5a: memoryRead(); break; // *NOP (implied)
case 0x5b: sre(AM_AbsoluteY()); break; // *SRE (absolute, Y) case 0x5b: sre(AM_AbsoluteY()); break; // *SRE (absolute, Y)
case 0x5c: AM_AbsoluteX(); break; // *NOP (absolute, X) case 0x5c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x5d: A() = eorr(A(), AM_AbsoluteX()); break; // EOR (absolute, X) case 0x5d: A() = eorr(A(), AM_AbsoluteX()); break; // EOR (absolute, X)
case 0x5e: memoryReadModifyWrite(lsr(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // LSR (absolute, X) case 0x5e: memoryReadModifyWrite(lsr(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // LSR (absolute, X)
case 0x5f: sre(AM_AbsoluteX()); break; // *SRE (absolute, X) case 0x5f: sre(AM_AbsoluteX()); break; // *SRE (absolute, X)
case 0x60: memoryRead(); rts(); break; // RTS (implied) case 0x60: memoryRead(); rts(); break; // RTS (implied)
case 0x61: A() = adc(A(), AM_IndexedIndirectX()); break; // ADC (indexed indirect X) case 0x61: A() = adc(A(), AM_IndexedIndirectX()); break; // ADC (indexed indirect X)
case 0x62: break; case 0x62: break;
case 0x63: rra(AM_IndexedIndirectX()); break; // *RRA (indexed indirect X) case 0x63: rra(AM_IndexedIndirectX()); break; // *RRA (indexed indirect X)
@ -225,7 +225,7 @@ int EightBit::MOS6502::execute() {
case 0x68: memoryRead(); getBytePaged(1, S()); A() = through(pop()); break; // PLA (implied) case 0x68: memoryRead(); getBytePaged(1, S()); A() = through(pop()); break; // PLA (implied)
case 0x69: A() = adc(A(), AM_Immediate()); break; // ADC (immediate) case 0x69: A() = adc(A(), AM_Immediate()); break; // ADC (immediate)
case 0x6a: memoryRead(); A() = ror(A()); break; // ROR A (implied) case 0x6a: memoryRead(); A() = ror(A()); break; // ROR A (implied)
case 0x6b: arr(AM_Immediate()); break; // *ARR (immediate) case 0x6b: arr(AM_Immediate()); break; // *ARR (immediate)
case 0x6c: jump(Address_Indirect()); break; // JMP (indirect) case 0x6c: jump(Address_Indirect()); break; // JMP (indirect)
case 0x6d: A() = adc(A(), AM_Absolute()); break; // ADC (absolute) case 0x6d: A() = adc(A(), AM_Absolute()); break; // ADC (absolute)
case 0x6e: memoryReadModifyWrite(ror(AM_Absolute())); break; // ROR (absolute) case 0x6e: memoryReadModifyWrite(ror(AM_Absolute())); break; // ROR (absolute)
@ -238,15 +238,15 @@ int EightBit::MOS6502::execute() {
case 0x74: AM_ZeroPageX(); break; // *NOP (zero page, X) case 0x74: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x75: A() = adc(A(), AM_ZeroPageX()); break; // ADC (zero page, X) case 0x75: A() = adc(A(), AM_ZeroPageX()); break; // ADC (zero page, X)
case 0x76: memoryReadModifyWrite(ror(AM_ZeroPageX())); break; // ROR (zero page, X) case 0x76: memoryReadModifyWrite(ror(AM_ZeroPageX())); break; // ROR (zero page, X)
case 0x77: rra(AM_ZeroPageX()); break; // *RRA (zero page, X) case 0x77: rra(AM_ZeroPageX()); break; // *RRA (zero page, X)
case 0x78: memoryRead(); P() = setBit(P(), IF); break; // SEI (implied) case 0x78: memoryRead(); P() = setBit(P(), IF); break; // SEI (implied)
case 0x79: A() = adc(A(), AM_AbsoluteY()); break; // ADC (absolute, Y) case 0x79: A() = adc(A(), AM_AbsoluteY()); break; // ADC (absolute, Y)
case 0x7a: memoryRead(); break; // *NOP (implied) case 0x7a: memoryRead(); break; // *NOP (implied)
case 0x7b: rra(AM_AbsoluteY()); break; // *RRA (absolute, Y) case 0x7b: rra(AM_AbsoluteY()); break; // *RRA (absolute, Y)
case 0x7c: AM_AbsoluteX(); break; // *NOP (absolute, X) case 0x7c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x7d: A() = adc(A(), AM_AbsoluteX()); break; // ADC (absolute, X) case 0x7d: A() = adc(A(), AM_AbsoluteX()); break; // ADC (absolute, X)
case 0x7e: memoryReadModifyWrite(ror(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ROR (absolute, X) case 0x7e: memoryReadModifyWrite(ror(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ROR (absolute, X)
case 0x7f: rra(AM_AbsoluteX()); break; // *RRA (absolute, X) case 0x7f: rra(AM_AbsoluteX()); break; // *RRA (absolute, X)
case 0x80: AM_Immediate(); break; // *NOP (immediate) case 0x80: AM_Immediate(); break; // *NOP (immediate)
case 0x81: memoryWrite(Address_IndexedIndirectX(), A()); break; // STA (indexed indirect X) case 0x81: memoryWrite(Address_IndexedIndirectX(), A()); break; // STA (indexed indirect X)
@ -266,19 +266,19 @@ int EightBit::MOS6502::execute() {
case 0x8f: memoryWrite(Address_Absolute(), A() & X()); break; // *SAX (absolute) case 0x8f: memoryWrite(Address_Absolute(), A() & X()); break; // *SAX (absolute)
case 0x90: branch(!carry()); break; // BCC (relative) case 0x90: branch(!carry()); break; // BCC (relative)
case 0x91: AM_IndirectIndexedY(); memoryWrite(A()); break; // STA (indirect indexed Y) case 0x91: AM_IndirectIndexedY(); memoryWrite(A()); break; // STA (indirect indexed Y)
case 0x92: break; case 0x92: break;
case 0x93: break; case 0x93: break;
case 0x94: memoryWrite(Address_ZeroPageX(), Y()); break; // STY (zero page, X) case 0x94: memoryWrite(Address_ZeroPageX(), Y()); break; // STY (zero page, X)
case 0x95: memoryWrite(Address_ZeroPageX(), A()); break; // STA (zero page, X) case 0x95: memoryWrite(Address_ZeroPageX(), A()); break; // STA (zero page, X)
case 0x96: memoryWrite(Address_ZeroPageY(), X()); break; // STX (zero page, Y) case 0x96: memoryWrite(Address_ZeroPageY(), X()); break; // STX (zero page, Y)
case 0x97: memoryWrite(Address_ZeroPageY(), A() & X()); break; // *SAX (zero page, Y) case 0x97: memoryWrite(Address_ZeroPageY(), A() & X()); break; // *SAX (zero page, Y)
case 0x98: memoryRead(); A() = through(Y()); break; // TYA (implied) case 0x98: memoryRead(); A() = through(Y()); break; // TYA (implied)
case 0x99: sta_AbsoluteY(); break; // STA (absolute, Y) case 0x99: sta_AbsoluteY(); break; // STA (absolute, Y)
case 0x9a: memoryRead(); S() = X(); break; // TXS (implied) case 0x9a: memoryRead(); S() = X(); break; // TXS (implied)
case 0x9b: break; case 0x9b: break;
case 0x9c: break; case 0x9c: break;
case 0x9d: sta_AbsoluteX(); break; // STA (absolute, X) case 0x9d: sta_AbsoluteX(); break; // STA (absolute, X)
case 0x9e: break; case 0x9e: break;
case 0x9f: break; case 0x9f: break;
@ -293,20 +293,20 @@ int EightBit::MOS6502::execute() {
case 0xa8: memoryRead(); Y() = through(A()); break; // TAY (implied) case 0xa8: memoryRead(); Y() = through(A()); break; // TAY (implied)
case 0xa9: A() = through(AM_Immediate()); break; // LDA (immediate) case 0xa9: A() = through(AM_Immediate()); break; // LDA (immediate)
case 0xaa: memoryRead(); X() = through(A()); break; // TAX (implied) case 0xaa: memoryRead(); X() = through(A()); break; // TAX (implied)
case 0xab: A() = X() = through(AM_Immediate()); break; // *ATX (immediate) case 0xab: A() = X() = through(AM_Immediate()); break; // *ATX (immediate)
case 0xac: Y() = through(AM_Absolute()); break; // LDY (absolute) case 0xac: Y() = through(AM_Absolute()); break; // LDY (absolute)
case 0xad: A() = through(AM_Absolute()); break; // LDA (absolute) case 0xad: A() = through(AM_Absolute()); break; // LDA (absolute)
case 0xae: X() = through(AM_Absolute()); break; // LDX (absolute) case 0xae: X() = through(AM_Absolute()); break; // LDX (absolute)
case 0xaf: A() = X() = through(AM_Absolute()); break; // *LAX (absolute) case 0xaf: A() = X() = through(AM_Absolute()); break; // *LAX (absolute)
case 0xb0: branch(carry()); break; // BCS (relative) case 0xb0: branch(carry()); break; // BCS (relative)
case 0xb1: A() = through(AM_IndirectIndexedY()); break; // LDA (indirect indexed Y) case 0xb1: A() = through(AM_IndirectIndexedY()); break; // LDA (indirect indexed Y)
case 0xb2: break; case 0xb2: break;
case 0xb3: A() = X() = through(AM_IndirectIndexedY()); break; // *LAX (indirect indexed Y) case 0xb3: A() = X() = through(AM_IndirectIndexedY()); break; // *LAX (indirect indexed Y)
case 0xb4: Y() = through(AM_ZeroPageX()); break; // LDY (zero page, X) case 0xb4: Y() = through(AM_ZeroPageX()); break; // LDY (zero page, X)
case 0xb5: A() = through(AM_ZeroPageX()); break; // LDA (zero page, X) case 0xb5: A() = through(AM_ZeroPageX()); break; // LDA (zero page, X)
case 0xb6: X() = through(AM_ZeroPageY()); break; // LDX (zero page, Y) case 0xb6: X() = through(AM_ZeroPageY()); break; // LDX (zero page, Y)
case 0xb7: A() = X() = through(AM_ZeroPageY()); break; // *LAX (zero page, Y) case 0xb7: A() = X() = through(AM_ZeroPageY()); break; // *LAX (zero page, Y)
case 0xb8: memoryRead(); P() = clearBit(P(), VF); break; // CLV (implied) case 0xb8: memoryRead(); P() = clearBit(P(), VF); break; // CLV (implied)
case 0xb9: A() = through(AM_AbsoluteY()); break; // LDA (absolute, Y) case 0xb9: A() = through(AM_AbsoluteY()); break; // LDA (absolute, Y)
case 0xba: memoryRead(); X() = through(S()); break; // TSX (implied) case 0xba: memoryRead(); X() = through(S()); break; // TSX (implied)
@ -314,47 +314,47 @@ int EightBit::MOS6502::execute() {
case 0xbc: Y() = through(AM_AbsoluteX()); break; // LDY (absolute, X) case 0xbc: Y() = through(AM_AbsoluteX()); break; // LDY (absolute, X)
case 0xbd: A() = through(AM_AbsoluteX()); break; // LDA (absolute, X) case 0xbd: A() = through(AM_AbsoluteX()); break; // LDA (absolute, X)
case 0xbe: X() = through(AM_AbsoluteY()); break; // LDX (absolute, Y) case 0xbe: X() = through(AM_AbsoluteY()); break; // LDX (absolute, Y)
case 0xbf: A() = X() = through(AM_AbsoluteY()); break; // *LAX (absolute, Y) case 0xbf: A() = X() = through(AM_AbsoluteY()); break; // *LAX (absolute, Y)
case 0xc0: cmp(Y(), AM_Immediate()); break; // CPY (immediate) case 0xc0: cmp(Y(), AM_Immediate()); break; // CPY (immediate)
case 0xc1: cmp(A(), AM_IndexedIndirectX()); break; // CMP (indexed indirect X) case 0xc1: cmp(A(), AM_IndexedIndirectX()); break; // CMP (indexed indirect X)
case 0xc2: AM_Immediate(); break; // *NOP (immediate) case 0xc2: AM_Immediate(); break; // *NOP (immediate)
case 0xc3: dcp(AM_IndexedIndirectX()); break; // *DCP (indexed indirect X) case 0xc3: dcp(AM_IndexedIndirectX()); break; // *DCP (indexed indirect X)
case 0xc4: cmp(Y(), AM_ZeroPage()); break; // CPY (zero page) case 0xc4: cmp(Y(), AM_ZeroPage()); break; // CPY (zero page)
case 0xc5: cmp(A(), AM_ZeroPage()); break; // CMP (zero page) case 0xc5: cmp(A(), AM_ZeroPage()); break; // CMP (zero page)
case 0xc6: memoryReadModifyWrite(dec(AM_ZeroPage())); break; // DEC (zero page) case 0xc6: memoryReadModifyWrite(dec(AM_ZeroPage())); break; // DEC (zero page)
case 0xc7: dcp(AM_ZeroPage()); break; // *DCP (zero page) case 0xc7: dcp(AM_ZeroPage()); break; // *DCP (zero page)
case 0xc8: memoryRead(); Y() = inc(Y()); break; // INY (implied) case 0xc8: memoryRead(); Y() = inc(Y()); break; // INY (implied)
case 0xc9: cmp(A(), AM_Immediate()); break; // CMP (immediate) case 0xc9: cmp(A(), AM_Immediate()); break; // CMP (immediate)
case 0xca: memoryRead(); X() = dec(X()); break; // DEX (implied) case 0xca: memoryRead(); X() = dec(X()); break; // DEX (implied)
case 0xcb: axs(AM_Immediate()); break; // *AXS (immediate) case 0xcb: axs(AM_Immediate()); break; // *AXS (immediate)
case 0xcc: cmp(Y(), AM_Absolute()); break; // CPY (absolute) case 0xcc: cmp(Y(), AM_Absolute()); break; // CPY (absolute)
case 0xcd: cmp(A(), AM_Absolute()); break; // CMP (absolute) case 0xcd: cmp(A(), AM_Absolute()); break; // CMP (absolute)
case 0xce: memoryReadModifyWrite(dec(AM_Absolute())); break; // DEC (absolute) case 0xce: memoryReadModifyWrite(dec(AM_Absolute())); break; // DEC (absolute)
case 0xcf: dcp(AM_Absolute()); break; // *DCP (absolute) case 0xcf: dcp(AM_Absolute()); break; // *DCP (absolute)
case 0xd0: branch(!zero()); break; // BNE (relative) case 0xd0: branch(!zero()); break; // BNE (relative)
case 0xd1: cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y) case 0xd1: cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y)
case 0xd2: break; case 0xd2: break;
case 0xd3: dcp(AM_IndirectIndexedY()); break; // *DCP (indirect indexed Y) case 0xd3: dcp(AM_IndirectIndexedY()); break; // *DCP (indirect indexed Y)
case 0xd4: AM_ZeroPageX(); break; // *NOP (zero page, X) case 0xd4: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0xd5: cmp(A(), AM_ZeroPageX()); break; // CMP (zero page, X) case 0xd5: cmp(A(), AM_ZeroPageX()); break; // CMP (zero page, X)
case 0xd6: memoryReadModifyWrite(dec(AM_ZeroPageX())); break; // DEC (zero page, X) case 0xd6: memoryReadModifyWrite(dec(AM_ZeroPageX())); break; // DEC (zero page, X)
case 0xd7: dcp(AM_ZeroPageX()); break; // *DCP (zero page, X) case 0xd7: dcp(AM_ZeroPageX()); break; // *DCP (zero page, X)
case 0xd8: memoryRead(); P() = clearBit(P(), DF); break; // CLD (implied) case 0xd8: memoryRead(); P() = clearBit(P(), DF); break; // CLD (implied)
case 0xd9: cmp(A(), AM_AbsoluteY()); break; // CMP (absolute, Y) case 0xd9: cmp(A(), AM_AbsoluteY()); break; // CMP (absolute, Y)
case 0xda: memoryRead(); break; // *NOP (implied) case 0xda: memoryRead(); break; // *NOP (implied)
case 0xdb: dcp(AM_AbsoluteY()); break; // *DCP (absolute, Y) case 0xdb: dcp(AM_AbsoluteY()); break; // *DCP (absolute, Y)
case 0xdc: AM_AbsoluteX(); break; // *NOP (absolute, X) case 0xdc: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0xdd: cmp(A(), AM_AbsoluteX()); break; // CMP (absolute, X) case 0xdd: cmp(A(), AM_AbsoluteX()); break; // CMP (absolute, X)
case 0xde: memoryReadModifyWrite(dec(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // DEC (absolute, X) case 0xde: memoryReadModifyWrite(dec(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // DEC (absolute, X)
case 0xdf: dcp(AM_AbsoluteX()); break; // *DCP (absolute, X) case 0xdf: dcp(AM_AbsoluteX()); break; // *DCP (absolute, X)
case 0xe0: cmp(X(), AM_Immediate()); break; // CPX (immediate) case 0xe0: cmp(X(), AM_Immediate()); break; // CPX (immediate)
case 0xe1: A() = sbc(A(), AM_IndexedIndirectX()); break; // SBC (indexed indirect X) case 0xe1: A() = sbc(A(), AM_IndexedIndirectX()); break; // SBC (indexed indirect X)
case 0xe2: AM_Immediate(); break; // *NOP (immediate) case 0xe2: AM_Immediate(); break; // *NOP (immediate)
case 0xe3: isb(AM_IndexedIndirectX()); break; // *ISB (indexed indirect X) case 0xe3: isb(AM_IndexedIndirectX()); break; // *ISB (indexed indirect X)
case 0xe4: cmp(X(), AM_ZeroPage()); break; // CPX (zero page) case 0xe4: cmp(X(), AM_ZeroPage()); break; // CPX (zero page)
case 0xe5: A() = sbc(A(), AM_ZeroPage()); break; // SBC (zero page) case 0xe5: A() = sbc(A(), AM_ZeroPage()); break; // SBC (zero page)
case 0xe6: memoryReadModifyWrite(inc(AM_ZeroPage())); break; // INC (zero page) case 0xe6: memoryReadModifyWrite(inc(AM_ZeroPage())); break; // INC (zero page)
case 0xe7: isb(AM_ZeroPage()); break; // *ISB (zero page) case 0xe7: isb(AM_ZeroPage()); break; // *ISB (zero page)
@ -362,7 +362,7 @@ int EightBit::MOS6502::execute() {
case 0xe9: A() = sbc(A(), AM_Immediate()); break; // SBC (immediate) case 0xe9: A() = sbc(A(), AM_Immediate()); break; // SBC (immediate)
case 0xea: memoryRead(); break; // NOP (implied) case 0xea: memoryRead(); break; // NOP (implied)
case 0xeb: A() = sbc(A(), AM_Immediate()); break; // *SBC (immediate) case 0xeb: A() = sbc(A(), AM_Immediate()); break; // *SBC (immediate)
case 0xec: cmp(X(), AM_Absolute()); break; // CPX (absolute) case 0xec: cmp(X(), AM_Absolute()); break; // CPX (absolute)
case 0xed: A() = sbc(A(), AM_Absolute()); break; // SBC (absolute) case 0xed: A() = sbc(A(), AM_Absolute()); break; // SBC (absolute)
case 0xee: memoryReadModifyWrite(inc(AM_Absolute())); break; // INC (absolute) case 0xee: memoryReadModifyWrite(inc(AM_Absolute())); break; // INC (absolute)
case 0xef: isb(AM_Absolute()); break; // *ISB (absolute) case 0xef: isb(AM_Absolute()); break; // *ISB (absolute)
@ -374,15 +374,15 @@ int EightBit::MOS6502::execute() {
case 0xf4: AM_ZeroPageX(); break; // *NOP (zero page, X) case 0xf4: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0xf5: A() = sbc(A(), AM_ZeroPageX()); break; // SBC (zero page, X) case 0xf5: A() = sbc(A(), AM_ZeroPageX()); break; // SBC (zero page, X)
case 0xf6: memoryReadModifyWrite(inc(AM_ZeroPageX())); break; // INC (zero page, X) case 0xf6: memoryReadModifyWrite(inc(AM_ZeroPageX())); break; // INC (zero page, X)
case 0xf7: isb(AM_ZeroPageX()); break; // *ISB (zero page, X) case 0xf7: isb(AM_ZeroPageX()); break; // *ISB (zero page, X)
case 0xf8: memoryRead(); P() = setBit(P(), DF); break; // SED (implied) case 0xf8: memoryRead(); P() = setBit(P(), DF); break; // SED (implied)
case 0xf9: A() = sbc(A(), AM_AbsoluteY()); break; // SBC (absolute, Y) case 0xf9: A() = sbc(A(), AM_AbsoluteY()); break; // SBC (absolute, Y)
case 0xfa: memoryRead(); break; // *NOP (implied) case 0xfa: memoryRead(); break; // *NOP (implied)
case 0xfb: isb(AM_AbsoluteY()); break; // *ISB (absolute, Y) case 0xfb: isb(AM_AbsoluteY()); break; // *ISB (absolute, Y)
case 0xfc: AM_AbsoluteX(); break; // *NOP (absolute, X) case 0xfc: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0xfd: A() = sbc(A(), AM_AbsoluteX()); break; // SBC (absolute, X) case 0xfd: A() = sbc(A(), AM_AbsoluteX()); break; // SBC (absolute, X)
case 0xfe: memoryReadModifyWrite(inc(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // INC (absolute, X) case 0xfe: memoryReadModifyWrite(inc(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // INC (absolute, X)
case 0xff: isb(AM_AbsoluteX()); break; // *ISB (absolute, X) case 0xff: isb(AM_AbsoluteX()); break; // *ISB (absolute, X)
} }
ASSUME(cycles() > 0); ASSUME(cycles() > 0);

View File

@ -23,7 +23,7 @@ void EightBit::M6532::step() {
if (!activated()) if (!activated())
return; return;
Accessing.fire(EventArgs::empty()); Accessing.fire();
if (lowered(RES())) { if (lowered(RES())) {
reset(); reset();
@ -120,7 +120,7 @@ void EightBit::M6532::step() {
} }
} }
Accessed.fire(EventArgs::empty()); Accessed.fire();
} }
void EightBit::M6532::reset() { void EightBit::M6532::reset() {

View File

@ -12,11 +12,24 @@ namespace EightBit {
public: public:
Disassembly(Bus& bus, mc6809& processor); Disassembly(Bus& bus, mc6809& processor);
bool ignore(); [[nodiscard]] bool ignore();
std::string trace(uint16_t current); [[nodiscard]] std::string trace(uint16_t current);
std::string trace(register16_t current); [[nodiscard]] std::string disassemble(uint16_t current);
std::string trace();
[[nodiscard]] std::string trace(register16_t current);
[[nodiscard]] std::string disassemble(register16_t current);
[[nodiscard]] std::string trace();
[[nodiscard]] std::string disassemble();
static [[nodiscard]] std::string dump_Flags(uint8_t value);
static [[nodiscard]] std::string dump_ByteValue(uint8_t value);
static [[nodiscard]] std::string dump_RelativeValue(int8_t value);
static [[nodiscard]] std::string dump_WordValue(uint16_t value);
static [[nodiscard]] std::string dump_WordValue(register16_t value);
static [[nodiscard]] std::string dump_RelativeValue(int16_t value);
static [[nodiscard]] std::string dump_RelativeValue(register16_t value);
private: private:
Bus& m_bus; Bus& m_bus;
@ -27,63 +40,50 @@ namespace EightBit {
bool m_prefix10 = false; bool m_prefix10 = false;
bool m_prefix11 = false; bool m_prefix11 = false;
static std::string dump_Flags(uint8_t value);
static std::string dump_ByteValue(uint8_t value);
static std::string dump_RelativeValue(int8_t value);
static std::string dump_WordValue(uint16_t value);
static std::string dump_WordValue(register16_t value);
static std::string dump_RelativeValue(int16_t value);
static std::string dump_RelativeValue(register16_t value);
std::string disassemble(uint16_t current);
std::string disassemble(register16_t current);
std::string disassemble();
static void dump(std::ostream& out, int value, int width); static void dump(std::ostream& out, int value, int width);
mc6809& CPU() { return m_cpu; } [[nodiscard]] mc6809& CPU() { return m_cpu; }
[[nodiscard]] Bus& BUS() { return m_bus; }
uint8_t getByte(uint16_t address); [[nodiscard]] uint8_t getByte(uint16_t address);
uint16_t getWord(uint16_t address); [[nodiscard]] uint16_t getWord(uint16_t address);
std::string disassembleUnprefixed(); [[nodiscard]] std::string disassembleUnprefixed();
std::string disassemble10(); [[nodiscard]] std::string disassemble10();
std::string disassemble11(); [[nodiscard]] std::string disassemble11();
// //
std::string RR(int which); [[nodiscard]] std::string RR(int which);
std::string wrapIndirect(std::string what, bool indirect); [[nodiscard]] std::string wrapIndirect(std::string what, bool indirect);
std::string Address_direct(std::string mnemomic); [[nodiscard]] std::string Address_direct(std::string mnemomic);
std::string Address_indexed(std::string mnemomic); [[nodiscard]] std::string Address_indexed(std::string mnemomic);
std::string Address_extended(std::string mnemomic); [[nodiscard]] std::string Address_extended(std::string mnemomic);
std::string Address_relative_byte(std::string mnemomic); [[nodiscard]] std::string Address_relative_byte(std::string mnemomic);
std::string Address_relative_word(std::string mnemomic); [[nodiscard]] std::string Address_relative_word(std::string mnemomic);
std::string AM_immediate_byte(std::string mnemomic); [[nodiscard]] std::string AM_immediate_byte(std::string mnemomic);
std::string AM_immediate_word(std::string mnemomic); [[nodiscard]] std::string AM_immediate_word(std::string mnemomic);
// //
std::string branchShort(std::string mnemomic); [[nodiscard]] std::string branchShort(std::string mnemomic);
std::string branchLong(std::string mnemomic); [[nodiscard]] std::string branchLong(std::string mnemomic);
// //
std::string referenceTransfer8(int specifier); [[nodiscard]] std::string referenceTransfer8(int specifier);
std::string referenceTransfer16(int specifier); [[nodiscard]] std::string referenceTransfer16(int specifier);
std::string tfr(std::string mnemomic); [[nodiscard]] std::string tfr(std::string mnemomic);
// //
std::string pulS(); [[nodiscard]] std::string pulS();
std::string pulU(); [[nodiscard]] std::string pulU();
std::string pshS(); [[nodiscard]] std::string pshS();
std::string pshU(); [[nodiscard]] std::string pshU();
std::string pulX(std::string mnemomic, std::string upon); [[nodiscard]] std::string pulX(std::string mnemomic, std::string upon);
std::string pshX(std::string mnemomic, std::string upon); [[nodiscard]] std::string pshX(std::string mnemomic, std::string upon);
Bus& BUS() { return m_bus; }
}; };
} }

View File

@ -0,0 +1,22 @@
#pragma once
#include <string>
#include <cstdint>
namespace EightBit {
class ProfileLineEventArgs
{
private:
int m_address;
std::string m_source;
uint64_t m_cycles;
public:
ProfileLineEventArgs(int address, std::string source, uint64_t cycles)
: m_address(address), m_source(source), m_cycles(cycles) {}
int address() const { return m_address; }
const std::string& source() const { return m_source; }
uint64_t cycles() const { return m_cycles; }
};
}

41
MC6809/inc/Profiler.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include <array>
#include <cstdint>
#include <map>
#include <EventArgs.h>
#include <Signal.h>
#include "ProfileLineEventArgs.h"
namespace EightBit {
class Disassembly;
class mc6809;
class Profiler {
public:
std::array<uint64_t, 0x100> instructionCounts;
std::array<uint64_t, 0x10000> addressProfiles;
std::array<uint64_t, 0x10000> addressCounts;
mc6809& processor;
Disassembly& disassembler;
Profiler(mc6809& processor, Disassembly& disassembler);
Signal<EventArgs> StartingOutput;
Signal<EventArgs> FinishedOutput;
Signal<ProfileLineEventArgs> EmitLine;
void addInstruction(uint8_t instruction);
void addAddress(uint16_t address, int cycles);
void Generate();
private:
void EmitProfileInformation();
};
}

View File

@ -146,39 +146,39 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x3a: output << "\tABX"; break; // ABX (inherent) case 0x3a: output << "\tABX"; break; // ABX (inherent)
// ADC // ADC
case 0x89: output << AM_immediate_byte("ADCA"); break; // ADC (ADCA immediate) case 0x89: output << AM_immediate_byte("ADCA"); break; // ADC (ADCA immediate)
case 0x99: output << Address_direct("ADCA"); break; // ADC (ADCA direct) case 0x99: output << Address_direct("ADCA"); break; // ADC (ADCA direct)
case 0xa9: output << Address_indexed("ADCA"); break; // ADC (ADCA indexed) case 0xa9: output << Address_indexed("ADCA"); break; // ADC (ADCA indexed)
case 0xb9: output << Address_extended("ADCA"); break; // ADC (ADCA extended) case 0xb9: output << Address_extended("ADCA"); break; // ADC (ADCA extended)
case 0xc9: output << AM_immediate_byte("ADCB"); break; // ADC (ADCB immediate) case 0xc9: output << AM_immediate_byte("ADCB"); break; // ADC (ADCB immediate)
case 0xd9: output << Address_direct("ADCB"); break; // ADC (ADCB direct) case 0xd9: output << Address_direct("ADCB"); break; // ADC (ADCB direct)
case 0xe9: output << Address_indexed("ADCB"); break; // ADC (ADCB indexed) case 0xe9: output << Address_indexed("ADCB"); break; // ADC (ADCB indexed)
case 0xf9: output << Address_extended("ADCB"); break; // ADC (ADCB extended) case 0xf9: output << Address_extended("ADCB"); break; // ADC (ADCB extended)
// ADD // ADD
case 0x8b: output << Address_extended("ADDA"); break; // ADD (ADDA immediate) case 0x8b: output << Address_extended("ADDA"); break; // ADD (ADDA immediate)
case 0x9b: output << Address_direct("ADDA"); break; // ADD (ADDA direct) case 0x9b: output << Address_direct("ADDA"); break; // ADD (ADDA direct)
case 0xab: output << Address_indexed("ADDA"); break; // ADD (ADDA indexed) case 0xab: output << Address_indexed("ADDA"); break; // ADD (ADDA indexed)
case 0xbb: output << Address_extended("ADDA"); break; // ADD (ADDA extended) case 0xbb: output << Address_extended("ADDA"); break; // ADD (ADDA extended)
case 0xcb: output << Address_extended("ADDB"); break; // ADD (ADDB immediate) case 0xcb: output << Address_extended("ADDB"); break; // ADD (ADDB immediate)
case 0xdb: output << Address_direct("ADDB"); break; // ADD (ADDB direct) case 0xdb: output << Address_direct("ADDB"); break; // ADD (ADDB direct)
case 0xeb: output << Address_indexed("ADDB"); break; // ADD (ADDB indexed) case 0xeb: output << Address_indexed("ADDB"); break; // ADD (ADDB indexed)
case 0xfb: output << Address_extended("ADDB"); break; // ADD (ADDB extended) case 0xfb: output << Address_extended("ADDB"); break; // ADD (ADDB extended)
case 0xc3: output << AM_immediate_word("ADDD"); break; // ADD (ADDD immediate) case 0xc3: output << AM_immediate_word("ADDD"); break; // ADD (ADDD immediate)
case 0xd3: output << Address_direct("ADDD"); break; // ADD (ADDD direct) case 0xd3: output << Address_direct("ADDD"); break; // ADD (ADDD direct)
case 0xe3: output << Address_indexed("ADDD"); break; // ADD (ADDD indexed) case 0xe3: output << Address_indexed("ADDD"); break; // ADD (ADDD indexed)
case 0xf3: output << Address_extended("ADDD"); break; // ADD (ADDD extended) case 0xf3: output << Address_extended("ADDD"); break; // ADD (ADDD extended)
// AND // AND
case 0x84: output << AM_immediate_byte("ANDA"); break; // AND (ANDA immediate) case 0x84: output << AM_immediate_byte("ANDA"); break; // AND (ANDA immediate)
case 0x94: output << Address_direct("ANDA"); break; // AND (ANDA direct) case 0x94: output << Address_direct("ANDA"); break; // AND (ANDA direct)
case 0xa4: output << Address_indexed("ANDA"); break; // AND (ANDA indexed) case 0xa4: output << Address_indexed("ANDA"); break; // AND (ANDA indexed)
case 0xb4: output << Address_extended("ANDA"); break; // AND (ANDA extended) case 0xb4: output << Address_extended("ANDA"); break; // AND (ANDA extended)
case 0xc4: output << AM_immediate_byte("ANDB"); break; // AND (ANDB immediate) case 0xc4: output << AM_immediate_byte("ANDB"); break; // AND (ANDB immediate)
case 0xd4: output << Address_direct("ANDB"); break; // AND (ANDB direct) case 0xd4: output << Address_direct("ANDB"); break; // AND (ANDB direct)
case 0xe4: output << Address_indexed("ANDB"); break; // AND (ANDB indexed) case 0xe4: output << Address_indexed("ANDB"); break; // AND (ANDB indexed)
case 0xf4: output << Address_extended("ANDB"); break; // AND (ANDB extended) case 0xf4: output << Address_extended("ANDB"); break; // AND (ANDB extended)
@ -186,32 +186,32 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x1c: output << AM_immediate_byte("ANDCC"); break; // AND (ANDCC immediate) case 0x1c: output << AM_immediate_byte("ANDCC"); break; // AND (ANDCC immediate)
// ASL/LSL // ASL/LSL
case 0x08: output << Address_direct("ASL"); break; // ASL (direct) case 0x08: output << Address_direct("ASL"); break; // ASL (direct)
case 0x48: output << "\tASLA\t"; break; // ASL (ASLA inherent) case 0x48: output << "\tASLA\t"; break; // ASL (ASLA inherent)
case 0x58: output << "\tASLB\t"; break; // ASL (ASLB inherent) case 0x58: output << "\tASLB\t"; break; // ASL (ASLB inherent)
case 0x68: output << Address_indexed("ASL"); break; // ASL (indexed) case 0x68: output << Address_indexed("ASL"); break; // ASL (indexed)
case 0x78: output << Address_extended("ASL"); break; // ASL (extended) case 0x78: output << Address_extended("ASL"); break; // ASL (extended)
// ASR // ASR
case 0x07: output << Address_direct("ASR"); break; // ASR (direct) case 0x07: output << Address_direct("ASR"); break; // ASR (direct)
case 0x47: output << "\tASRA\t"; break; // ASR (ASRA inherent) case 0x47: output << "\tASRA\t"; break; // ASR (ASRA inherent)
case 0x57: output << "\tASRB\t"; break; // ASR (ASRB inherent) case 0x57: output << "\tASRB\t"; break; // ASR (ASRB inherent)
case 0x67: output << Address_indexed("ASR"); break; // ASR (indexed) case 0x67: output << Address_indexed("ASR"); break; // ASR (indexed)
case 0x77: output << Address_extended("ASR"); break; // ASR (extended) case 0x77: output << Address_extended("ASR"); break; // ASR (extended)
// BIT // BIT
case 0x85: output << AM_immediate_byte("BITA"); break; // BIT (BITA immediate) case 0x85: output << AM_immediate_byte("BITA"); break; // BIT (BITA immediate)
case 0x95: output << Address_direct("BITA"); break; // BIT (BITA direct) case 0x95: output << Address_direct("BITA"); break; // BIT (BITA direct)
case 0xa5: output << Address_indexed("BITA"); break; // BIT (BITA indexed) case 0xa5: output << Address_indexed("BITA"); break; // BIT (BITA indexed)
case 0xb5: output << Address_extended("BITA"); break; // BIT (BITA extended) case 0xb5: output << Address_extended("BITA"); break; // BIT (BITA extended)
case 0xc5: output << AM_immediate_byte("BITB"); break; // BIT (BITB immediate) case 0xc5: output << AM_immediate_byte("BITB"); break; // BIT (BITB immediate)
case 0xd5: output << Address_direct("BITB"); break; // BIT (BITB direct) case 0xd5: output << Address_direct("BITB"); break; // BIT (BITB direct)
case 0xe5: output << Address_indexed("BITB"); break; // BIT (BITB indexed) case 0xe5: output << Address_indexed("BITB"); break; // BIT (BITB indexed)
case 0xf5: output << Address_extended("BITB"); break; // BIT (BITB extended) case 0xf5: output << Address_extended("BITB"); break; // BIT (BITB extended)
// CLR // CLR
case 0x0f: output << Address_direct("CLR"); break; // CLR (direct) case 0x0f: output << Address_direct("CLR"); break; // CLR (direct)
case 0x4f: output << "\tCLRA\t"; break; // CLR (CLRA implied) case 0x4f: output << "\tCLRA\t"; break; // CLR (CLRA implied)
case 0x5f: output << "\tCLRB\t"; break; // CLR (CLRB implied) case 0x5f: output << "\tCLRB\t"; break; // CLR (CLRB implied)
case 0x6f: output << Address_indexed("CLR"); break; // CLR (indexed) case 0x6f: output << Address_indexed("CLR"); break; // CLR (indexed)
@ -220,25 +220,25 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
// CMP // CMP
// CMPA // CMPA
case 0x81: output << AM_immediate_byte("CMPA"); break; // CMP (CMPA, immediate) case 0x81: output << AM_immediate_byte("CMPA"); break; // CMP (CMPA, immediate)
case 0x91: output << Address_direct("CMPA"); break; // CMP (CMPA, direct) case 0x91: output << Address_direct("CMPA"); break; // CMP (CMPA, direct)
case 0xa1: output << Address_indexed("CMPA"); break; // CMP (CMPA, indexed) case 0xa1: output << Address_indexed("CMPA"); break; // CMP (CMPA, indexed)
case 0xb1: output << Address_extended("CMPA"); break; // CMP (CMPA, extended) case 0xb1: output << Address_extended("CMPA"); break; // CMP (CMPA, extended)
// CMPB // CMPB
case 0xc1: output << AM_immediate_byte("CMPB"); break; // CMP (CMPB, immediate) case 0xc1: output << AM_immediate_byte("CMPB"); break; // CMP (CMPB, immediate)
case 0xd1: output << Address_direct("CMPB"); break; // CMP (CMPB, direct) case 0xd1: output << Address_direct("CMPB"); break; // CMP (CMPB, direct)
case 0xe1: output << Address_indexed("CMPB"); break; // CMP (CMPB, indexed) case 0xe1: output << Address_indexed("CMPB"); break; // CMP (CMPB, indexed)
case 0xf1: output << Address_extended("CMPB"); break; // CMP (CMPB, extended) case 0xf1: output << Address_extended("CMPB"); break; // CMP (CMPB, extended)
// CMPX // CMPX
case 0x8c: output << AM_immediate_word("CMPX"); break; // CMP (CMPX, immediate) case 0x8c: output << AM_immediate_word("CMPX"); break; // CMP (CMPX, immediate)
case 0x9c: output << Address_direct("CMPX"); break; // CMP (CMPX, direct) case 0x9c: output << Address_direct("CMPX"); break; // CMP (CMPX, direct)
case 0xac: output << Address_indexed("CMPX"); break; // CMP (CMPX, indexed) case 0xac: output << Address_indexed("CMPX"); break; // CMP (CMPX, indexed)
case 0xbc: output << Address_extended("CMPX"); break; // CMP (CMPX, extended) case 0xbc: output << Address_extended("CMPX"); break; // CMP (CMPX, extended)
// COM // COM
case 0x03: output << Address_direct("COM"); break; // COM (direct) case 0x03: output << Address_direct("COM"); break; // COM (direct)
case 0x43: output << "\tCOMA\t"; break; // COM (COMA inherent) case 0x43: output << "\tCOMA\t"; break; // COM (COMA inherent)
case 0x53: output << "\tCOMB\t"; break; // COM (COMB inherent) case 0x53: output << "\tCOMB\t"; break; // COM (COMB inherent)
case 0x63: output << Address_indexed("COM"); break; // COM (indexed) case 0x63: output << Address_indexed("COM"); break; // COM (indexed)
@ -251,7 +251,7 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x19: output << "\tDAA"; break; // DAA (inherent) case 0x19: output << "\tDAA"; break; // DAA (inherent)
// DEC // DEC
case 0x0a: output << Address_direct("DEC"); break; // DEC (direct) case 0x0a: output << Address_direct("DEC"); break; // DEC (direct)
case 0x4a: output << "\tDECA\t"; break; // DEC (DECA inherent) case 0x4a: output << "\tDECA\t"; break; // DEC (DECA inherent)
case 0x5a: output << "\tDECB\t"; break; // DEC (DECB inherent) case 0x5a: output << "\tDECB\t"; break; // DEC (DECB inherent)
case 0x6a: output << Address_indexed("DEC"); break; // DEC (indexed) case 0x6a: output << Address_indexed("DEC"); break; // DEC (indexed)
@ -260,13 +260,13 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
// EOR // EOR
// EORA // EORA
case 0x88: output << AM_immediate_byte("EORA"); break; // EOR (EORA immediate) case 0x88: output << AM_immediate_byte("EORA"); break; // EOR (EORA immediate)
case 0x98: output << Address_direct("EORA"); break; // EOR (EORA direct) case 0x98: output << Address_direct("EORA"); break; // EOR (EORA direct)
case 0xa8: output << Address_indexed("EORA"); break; // EOR (EORA indexed) case 0xa8: output << Address_indexed("EORA"); break; // EOR (EORA indexed)
case 0xb8: output << Address_extended("EORA"); break; // EOR (EORA extended) case 0xb8: output << Address_extended("EORA"); break; // EOR (EORA extended)
// EORB // EORB
case 0xc8: output << AM_immediate_byte("EORB"); break; // EOR (EORB immediate) case 0xc8: output << AM_immediate_byte("EORB"); break; // EOR (EORB immediate)
case 0xd8: output << Address_direct("EORB"); break; // EOR (EORB direct) case 0xd8: output << Address_direct("EORB"); break; // EOR (EORB direct)
case 0xe8: output << Address_indexed("EORB"); break; // EOR (EORB indexed) case 0xe8: output << Address_indexed("EORB"); break; // EOR (EORB indexed)
case 0xf8: output << Address_extended("EORB"); break; // EOR (EORB extended) case 0xf8: output << Address_extended("EORB"); break; // EOR (EORB extended)
@ -275,19 +275,19 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x1e: output << tfr("EXG"); break; // EXG (R1,R2 immediate) case 0x1e: output << tfr("EXG"); break; // EXG (R1,R2 immediate)
// INC // INC
case 0x0c: output << Address_direct("INC"); break; // INC (direct) case 0x0c: output << Address_direct("INC"); break; // INC (direct)
case 0x4c: output << "\tINCA\t";; break; // INC (INCA inherent) case 0x4c: output << "\tINCA\t";; break; // INC (INCA inherent)
case 0x5c: output << "\tINCB\t";; break; // INC (INCB inherent) case 0x5c: output << "\tINCB\t";; break; // INC (INCB inherent)
case 0x6c: output << Address_indexed("INC"); break; // INC (indexed) case 0x6c: output << Address_indexed("INC"); break; // INC (indexed)
case 0x7c: output << Address_extended("INC"); break; // INC (extended) case 0x7c: output << Address_extended("INC"); break; // INC (extended)
// JMP // JMP
case 0x0e: output << Address_direct("JMP"); break; // JMP (direct) case 0x0e: output << Address_direct("JMP"); break; // JMP (direct)
case 0x6e: output << Address_indexed("JMP"); break; // JMP (indexed) case 0x6e: output << Address_indexed("JMP"); break; // JMP (indexed)
case 0x7e: output << Address_extended("JMP"); break; // JMP (extended) case 0x7e: output << Address_extended("JMP"); break; // JMP (extended)
// JSR // JSR
case 0x9d: output << Address_direct("JSR"); break; // JSR (direct) case 0x9d: output << Address_direct("JSR"); break; // JSR (direct)
case 0xad: output << Address_indexed("JSR"); break; // JSR (indexed) case 0xad: output << Address_indexed("JSR"); break; // JSR (indexed)
case 0xbd: output << Address_extended("JSR"); break; // JSR (extended) case 0xbd: output << Address_extended("JSR"); break; // JSR (extended)
@ -295,31 +295,31 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
// LDA // LDA
case 0x86: output << AM_immediate_byte("LDA"); break; // LD (LDA immediate) case 0x86: output << AM_immediate_byte("LDA"); break; // LD (LDA immediate)
case 0x96: output << Address_direct("LDA"); break; // LD (LDA direct) case 0x96: output << Address_direct("LDA"); break; // LD (LDA direct)
case 0xa6: output << Address_indexed("LDA"); break; // LD (LDA indexed) case 0xa6: output << Address_indexed("LDA"); break; // LD (LDA indexed)
case 0xb6: output << Address_extended("LDA"); break; // LD (LDA extended) case 0xb6: output << Address_extended("LDA"); break; // LD (LDA extended)
// LDB // LDB
case 0xc6: output << AM_immediate_byte("LDB"); break; // LD (LDB immediate) case 0xc6: output << AM_immediate_byte("LDB"); break; // LD (LDB immediate)
case 0xd6: output << Address_direct("LDB"); break; // LD (LDB direct) case 0xd6: output << Address_direct("LDB"); break; // LD (LDB direct)
case 0xe6: output << Address_indexed("LDB"); break; // LD (LDB indexed) case 0xe6: output << Address_indexed("LDB"); break; // LD (LDB indexed)
case 0xf6: output << Address_extended("LDB"); break; // LD (LDB extended) case 0xf6: output << Address_extended("LDB"); break; // LD (LDB extended)
// LDD // LDD
case 0xcc: output << AM_immediate_word("LDD"); break; // LD (LDD immediate) case 0xcc: output << AM_immediate_word("LDD"); break; // LD (LDD immediate)
case 0xdc: output << Address_direct("LDD"); break; // LD (LDD direct) case 0xdc: output << Address_direct("LDD"); break; // LD (LDD direct)
case 0xec: output << Address_indexed("LDD"); break; // LD (LDD indexed) case 0xec: output << Address_indexed("LDD"); break; // LD (LDD indexed)
case 0xfc: output << Address_extended("LDD"); break; // LD (LDD extended) case 0xfc: output << Address_extended("LDD"); break; // LD (LDD extended)
// LDU // LDU
case 0xce: output << AM_immediate_word("LDU"); break; // LD (LDU immediate) case 0xce: output << AM_immediate_word("LDU"); break; // LD (LDU immediate)
case 0xde: output << Address_direct("LDU"); break; // LD (LDU direct) case 0xde: output << Address_direct("LDU"); break; // LD (LDU direct)
case 0xee: output << Address_indexed("LDU"); break; // LD (LDU indexed) case 0xee: output << Address_indexed("LDU"); break; // LD (LDU indexed)
case 0xfe: output << Address_extended("LDU"); break; // LD (LDU extended) case 0xfe: output << Address_extended("LDU"); break; // LD (LDU extended)
// LDX // LDX
case 0x8e: output << AM_immediate_word("LDX"); break; // LD (LDX immediate) case 0x8e: output << AM_immediate_word("LDX"); break; // LD (LDX immediate)
case 0x9e: output << Address_direct("LDX"); break; // LD (LDX direct) case 0x9e: output << Address_direct("LDX"); break; // LD (LDX direct)
case 0xae: output << Address_indexed("LDX"); break; // LD (LDX indexed) case 0xae: output << Address_indexed("LDX"); break; // LD (LDX indexed)
case 0xbe: output << Address_extended("LDX"); break; // LD (LDX extended) case 0xbe: output << Address_extended("LDX"); break; // LD (LDX extended)
@ -330,41 +330,41 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x33: output << Address_indexed("LEAU"); break; // LEA (LEAU indexed) case 0x33: output << Address_indexed("LEAU"); break; // LEA (LEAU indexed)
// LSR // LSR
case 0x04: output << Address_direct("LSR"); break; // LSR (direct) case 0x04: output << Address_direct("LSR"); break; // LSR (direct)
case 0x44: output << "\tLSRA\t"; break; // LSR (LSRA inherent) case 0x44: output << "\tLSRA\t"; break; // LSR (LSRA inherent)
case 0x54: output << "\tLSRB\t"; break; // LSR (LSRB inherent) case 0x54: output << "\tLSRB\t"; break; // LSR (LSRB inherent)
case 0x64: output << Address_indexed("LSR"); break; // LSR (indexed) case 0x64: output << Address_indexed("LSR"); break; // LSR (indexed)
case 0x74: output << Address_extended("LSR"); break; // LSR (extended) case 0x74: output << Address_extended("LSR"); break; // LSR (extended)
// MUL // MUL
case 0x3d: output << "\tMUL\t"; break; // MUL (inherent) case 0x3d: output << "\tMUL\t"; break; // MUL (inherent)
// NEG // NEG
case 0x00: output << Address_direct("NEG"); break; // NEG (direct) case 0x00: output << Address_direct("NEG"); break; // NEG (direct)
case 0x40: output << "\tNEGA\t"; break; // NEG (NEGA, inherent) case 0x40: output << "\tNEGA\t"; break; // NEG (NEGA, inherent)
case 0x50: output << "\tNEGB\t"; break; // NEG (NEGB, inherent) case 0x50: output << "\tNEGB\t"; break; // NEG (NEGB, inherent)
case 0x60: output << Address_indexed("NEG"); break; // NEG (indexed) case 0x60: output << Address_indexed("NEG"); break; // NEG (indexed)
case 0x70: output << Address_extended("NEG"); break; // NEG (extended) case 0x70: output << Address_extended("NEG"); break; // NEG (extended)
// NOP // NOP
case 0x12: output << "\tNOP\t"; break; // NOP (inherent) case 0x12: output << "\tNOP\t"; break; // NOP (inherent)
// OR // OR
// ORA // ORA
case 0x8a: output << AM_immediate_byte("ORA"); break; // OR (ORA immediate) case 0x8a: output << AM_immediate_byte("ORA"); break; // OR (ORA immediate)
case 0x9a: output << Address_direct("ORA"); break; // OR (ORA direct) case 0x9a: output << Address_direct("ORA"); break; // OR (ORA direct)
case 0xaa: output << Address_indexed("ORA"); break; // OR (ORA indexed) case 0xaa: output << Address_indexed("ORA"); break; // OR (ORA indexed)
case 0xba: output << Address_extended("ORA"); break; // OR (ORA extended) case 0xba: output << Address_extended("ORA"); break; // OR (ORA extended)
// ORB // ORB
case 0xca: output << AM_immediate_byte("ORB"); break; // OR (ORB immediate) case 0xca: output << AM_immediate_byte("ORB"); break; // OR (ORB immediate)
case 0xda: output << Address_direct("ORB"); break; // OR (ORB direct) case 0xda: output << Address_direct("ORB"); break; // OR (ORB direct)
case 0xea: output << Address_indexed("ORB"); break; // OR (ORB indexed) case 0xea: output << Address_indexed("ORB"); break; // OR (ORB indexed)
case 0xfa: output << Address_extended("ORB"); break; // OR (ORB extended) case 0xfa: output << Address_extended("ORB"); break; // OR (ORB extended)
// ORCC // ORCC
case 0x1a: output << AM_immediate_byte("ORCC"); break; // OR (ORCC immediate) case 0x1a: output << AM_immediate_byte("ORCC"); break; // OR (ORCC immediate)
// PSH // PSH
case 0x34: output << pshS(); break; // PSH (PSHS immediate) case 0x34: output << pshS(); break; // PSH (PSHS immediate)
@ -375,91 +375,91 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x37: output << pulU(); break; // PUL (PULU immediate) case 0x37: output << pulU(); break; // PUL (PULU immediate)
// ROL // ROL
case 0x09: output << Address_direct("ROL"); break; // ROL (direct) case 0x09: output << Address_direct("ROL"); break; // ROL (direct)
case 0x49: output << "\tROLA\t"; break; // ROL (ROLA inherent) case 0x49: output << "\tROLA\t"; break; // ROL (ROLA inherent)
case 0x59: output << "\tROLB\t"; break; // ROL (ROLB inherent) case 0x59: output << "\tROLB\t"; break; // ROL (ROLB inherent)
case 0x69: output << Address_indexed("ROL"); break; // ROL (indexed) case 0x69: output << Address_indexed("ROL"); break; // ROL (indexed)
case 0x79: output << Address_extended("ROL"); break; // ROL (extended) case 0x79: output << Address_extended("ROL"); break; // ROL (extended)
// ROR // ROR
case 0x06: output << Address_direct("ROR"); break; // ROR (direct) case 0x06: output << Address_direct("ROR"); break; // ROR (direct)
case 0x46: output << "\tRORA\t"; break; // ROR (RORA inherent) case 0x46: output << "\tRORA\t"; break; // ROR (RORA inherent)
case 0x56: output << "\tRORB\t"; break; // ROR (RORB inherent) case 0x56: output << "\tRORB\t"; break; // ROR (RORB inherent)
case 0x66: output << Address_indexed("ROR"); break; // ROR (indexed) case 0x66: output << Address_indexed("ROR"); break; // ROR (indexed)
case 0x76: output << Address_extended("ROR"); break; // ROR (extended) case 0x76: output << Address_extended("ROR"); break; // ROR (extended)
// RTI // RTI
case 0x3B: output << "\tRTI\t"; break; // RTI (inherent) case 0x3B: output << "\tRTI\t"; break; // RTI (inherent)
// RTS // RTS
case 0x39: output << "\tRTS\t"; break; // RTS (inherent) case 0x39: output << "\tRTS\t"; break; // RTS (inherent)
// SBC // SBC
// SBCA // SBCA
case 0x82: output << AM_immediate_byte("SBCA"); break; // SBC (SBCA immediate) case 0x82: output << AM_immediate_byte("SBCA"); break; // SBC (SBCA immediate)
case 0x92: output << Address_direct("SBCA"); break; // SBC (SBCA direct) case 0x92: output << Address_direct("SBCA"); break; // SBC (SBCA direct)
case 0xa2: output << Address_indexed("SBCA"); break; // SBC (SBCA indexed) case 0xa2: output << Address_indexed("SBCA"); break; // SBC (SBCA indexed)
case 0xb2: output << Address_extended("SBCA"); break; // SBC (SBCA extended) case 0xb2: output << Address_extended("SBCA"); break; // SBC (SBCA extended)
// SBCB // SBCB
case 0xc2: output << AM_immediate_byte("SBCB"); break; // SBC (SBCB immediate) case 0xc2: output << AM_immediate_byte("SBCB"); break; // SBC (SBCB immediate)
case 0xd2: output << Address_direct("SBCB"); break; // SBC (SBCB direct) case 0xd2: output << Address_direct("SBCB"); break; // SBC (SBCB direct)
case 0xe2: output << Address_indexed("SBCB"); break; // SBC (SBCB indexed) case 0xe2: output << Address_indexed("SBCB"); break; // SBC (SBCB indexed)
case 0xf2: output << Address_extended("SBCB"); break; // SBC (SBCB extended) case 0xf2: output << Address_extended("SBCB"); break; // SBC (SBCB extended)
// SEX // SEX
case 0x1d: output << "\tSEX\t"; break; // SEX (inherent) case 0x1d: output << "\tSEX\t"; break; // SEX (inherent)
// ST // ST
// STA // STA
case 0x97: output << Address_direct("STA"); break; // ST (STA direct) case 0x97: output << Address_direct("STA"); break; // ST (STA direct)
case 0xa7: output << Address_indexed("STA"); break; // ST (STA indexed) case 0xa7: output << Address_indexed("STA"); break; // ST (STA indexed)
case 0xb7: output << Address_extended("STA"); break; // ST (STA extended) case 0xb7: output << Address_extended("STA"); break; // ST (STA extended)
// STB // STB
case 0xd7: output << Address_direct("STB"); break; // ST (STB direct) case 0xd7: output << Address_direct("STB"); break; // ST (STB direct)
case 0xe7: output << Address_indexed("STB"); break; // ST (STB indexed) case 0xe7: output << Address_indexed("STB"); break; // ST (STB indexed)
case 0xf7: output << Address_extended("STB"); break; // ST (STB extended) case 0xf7: output << Address_extended("STB"); break; // ST (STB extended)
// STD // STD
case 0xdd: output << Address_direct("STD"); break; // ST (STD direct) case 0xdd: output << Address_direct("STD"); break; // ST (STD direct)
case 0xed: output << Address_indexed("STD"); break; // ST (STD indexed) case 0xed: output << Address_indexed("STD"); break; // ST (STD indexed)
case 0xfd: output << Address_extended("STD"); break; // ST (STD extended) case 0xfd: output << Address_extended("STD"); break; // ST (STD extended)
// STU // STU
case 0xdf: output << Address_direct("STU"); break; // ST (STU direct) case 0xdf: output << Address_direct("STU"); break; // ST (STU direct)
case 0xef: output << Address_indexed("STU"); break; // ST (STU indexed) case 0xef: output << Address_indexed("STU"); break; // ST (STU indexed)
case 0xff: output << Address_extended("STU"); break; // ST (STU extended) case 0xff: output << Address_extended("STU"); break; // ST (STU extended)
// STX // STX
case 0x9f: output << Address_direct("STX"); break; // ST (STX direct) case 0x9f: output << Address_direct("STX"); break; // ST (STX direct)
case 0xaf: output << Address_indexed("STX"); break; // ST (STX indexed) case 0xaf: output << Address_indexed("STX"); break; // ST (STX indexed)
case 0xbf: output << Address_extended("STX"); break; // ST (STX extended) case 0xbf: output << Address_extended("STX"); break; // ST (STX extended)
// SUB // SUB
// SUBA // SUBA
case 0x80: output << AM_immediate_byte("SUBA"); break; // SUB (SUBA immediate) case 0x80: output << AM_immediate_byte("SUBA"); break; // SUB (SUBA immediate)
case 0x90: output << Address_direct("SUBA"); break; // SUB (SUBA direct) case 0x90: output << Address_direct("SUBA"); break; // SUB (SUBA direct)
case 0xa0: output << Address_indexed("SUBA"); break; // SUB (SUBA indexed) case 0xa0: output << Address_indexed("SUBA"); break; // SUB (SUBA indexed)
case 0xb0: output << Address_extended("SUBA"); break; // SUB (SUBA extended) case 0xb0: output << Address_extended("SUBA"); break; // SUB (SUBA extended)
// SUBB // SUBB
case 0xc0: output << AM_immediate_byte("SUBB"); break; // SUB (SUBB immediate) case 0xc0: output << AM_immediate_byte("SUBB"); break; // SUB (SUBB immediate)
case 0xd0: output << Address_direct("SUBB"); break; // SUB (SUBB direct) case 0xd0: output << Address_direct("SUBB"); break; // SUB (SUBB direct)
case 0xe0: output << Address_indexed("SUBB"); break; // SUB (SUBB indexed) case 0xe0: output << Address_indexed("SUBB"); break; // SUB (SUBB indexed)
case 0xf0: output << Address_extended("SUBB"); break; // SUB (SUBB extended) case 0xf0: output << Address_extended("SUBB"); break; // SUB (SUBB extended)
// SUBD // SUBD
case 0x83: output << AM_immediate_word("SUBD"); break; // SUB (SUBD immediate) case 0x83: output << AM_immediate_word("SUBD"); break; // SUB (SUBD immediate)
case 0x93: output << Address_direct("SUBD"); break; // SUB (SUBD direct) case 0x93: output << Address_direct("SUBD"); break; // SUB (SUBD direct)
case 0xa3: output << Address_indexed("SUBD"); break; // SUB (SUBD indexed) case 0xa3: output << Address_indexed("SUBD"); break; // SUB (SUBD indexed)
case 0xb3: output << Address_extended("SUBD"); break; // SUB (SUBD extended) case 0xb3: output << Address_extended("SUBD"); break; // SUB (SUBD extended)
// SWI // SWI
case 0x3f: output << "\tSWI\t"; break; // SWI (inherent) case 0x3f: output << "\tSWI\t"; break; // SWI (inherent)
// SYNC // SYNC
case 0x13: output << "\tSYNC\t"; break; // SYNC (inherent) case 0x13: output << "\tSYNC\t"; break; // SYNC (inherent)
@ -468,7 +468,7 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
case 0x1f: output << tfr("TFR"); break; // TFR (immediate) case 0x1f: output << tfr("TFR"); break; // TFR (immediate)
// TST // TST
case 0x0d: output << Address_direct("TST"); break; // TST (direct) case 0x0d: output << Address_direct("TST"); break; // TST (direct)
case 0x4d: output << "\tTSTA\t"; break; // TST (TSTA inherent) case 0x4d: output << "\tTSTA\t"; break; // TST (TSTA inherent)
case 0x5d: output << "\tTSTB\t"; break; // TST (TSTB inherent) case 0x5d: output << "\tTSTB\t"; break; // TST (TSTB inherent)
case 0x6d: output << Address_indexed("TST"); break; // TST (indexed) case 0x6d: output << Address_indexed("TST"); break; // TST (indexed)
@ -516,13 +516,13 @@ std::string EightBit::Disassembly::disassemble10() {
// CMP // CMP
// CMPD // CMPD
case 0x83: output << AM_immediate_word("CMPD"); break; // CMP (CMPD, immediate) case 0x83: output << AM_immediate_word("CMPD"); break; // CMP (CMPD, immediate)
case 0x93: output << Address_direct("CMPD"); break; // CMP (CMPD, direct) case 0x93: output << Address_direct("CMPD"); break; // CMP (CMPD, direct)
case 0xa3: output << Address_indexed("CMPD"); break; // CMP (CMPD, indexed) case 0xa3: output << Address_indexed("CMPD"); break; // CMP (CMPD, indexed)
case 0xb3: output << Address_extended("CMPD"); break; // CMP (CMPD, extended) case 0xb3: output << Address_extended("CMPD"); break; // CMP (CMPD, extended)
// CMPY // CMPY
case 0x8c: output << AM_immediate_word("CMPY"); break; // CMP (CMPY, immediate) case 0x8c: output << AM_immediate_word("CMPY"); break; // CMP (CMPY, immediate)
case 0x9c: output << Address_direct("CMPY"); break; // CMP (CMPY, direct) case 0x9c: output << Address_direct("CMPY"); break; // CMP (CMPY, direct)
case 0xac: output << Address_indexed("CMPY"); break; // CMP (CMPY, indexed) case 0xac: output << Address_indexed("CMPY"); break; // CMP (CMPY, indexed)
case 0xbc: output << Address_extended("CMPY"); break; // CMP (CMPY, extended) case 0xbc: output << Address_extended("CMPY"); break; // CMP (CMPY, extended)
@ -531,13 +531,13 @@ std::string EightBit::Disassembly::disassemble10() {
// LDS // LDS
case 0xce: output << AM_immediate_word("LDS"); break; // LD (LDS immediate) case 0xce: output << AM_immediate_word("LDS"); break; // LD (LDS immediate)
case 0xde: output << Address_direct("LDS"); break; // LD (LDS direct) case 0xde: output << Address_direct("LDS"); break; // LD (LDS direct)
case 0xee: output << Address_indexed("LDS"); break; // LD (LDS indexed) case 0xee: output << Address_indexed("LDS"); break; // LD (LDS indexed)
case 0xfe: output << Address_extended("LDS"); break; // LD (LDS extended) case 0xfe: output << Address_extended("LDS"); break; // LD (LDS extended)
// LDY // LDY
case 0x8e: output << AM_immediate_word("LDY"); break; // LD (LDY immediate) case 0x8e: output << AM_immediate_word("LDY"); break; // LD (LDY immediate)
case 0x9e: output << Address_direct("LDY"); break; // LD (LDY direct) case 0x9e: output << Address_direct("LDY"); break; // LD (LDY direct)
case 0xae: output << Address_indexed("LDY"); break; // LD (LDY indexed) case 0xae: output << Address_indexed("LDY"); break; // LD (LDY indexed)
case 0xbe: output << Address_extended("LDY"); break; // LD (LDY extended) case 0xbe: output << Address_extended("LDY"); break; // LD (LDY extended)
@ -560,7 +560,7 @@ std::string EightBit::Disassembly::disassemble10() {
case 0x2f: output << branchLong("LBLE"); break; // BLE (LBLE relative) case 0x2f: output << branchLong("LBLE"); break; // BLE (LBLE relative)
// STS // STS
case 0xdf: output << Address_direct("STS"); break; // ST (STS direct) case 0xdf: output << Address_direct("STS"); break; // ST (STS direct)
case 0xef: output << Address_indexed("STS"); break; // ST (STS indexed) case 0xef: output << Address_indexed("STS"); break; // ST (STS indexed)
case 0xff: output << Address_extended("STS"); break; // ST (STS extended) case 0xff: output << Address_extended("STS"); break; // ST (STS extended)
@ -593,13 +593,13 @@ std::string EightBit::Disassembly::disassemble11() {
// CMP // CMP
// CMPU // CMPU
case 0x83: output << AM_immediate_word("CMPU"); break; // CMP (CMPU, immediate) case 0x83: output << AM_immediate_word("CMPU"); break; // CMP (CMPU, immediate)
case 0x93: output << Address_direct("CMPU"); break; // CMP (CMPU, direct) case 0x93: output << Address_direct("CMPU"); break; // CMP (CMPU, direct)
case 0xa3: output << Address_indexed("CMPU"); break; // CMP (CMPU, indexed) case 0xa3: output << Address_indexed("CMPU"); break; // CMP (CMPU, indexed)
case 0xb3: output << Address_extended("CMPU"); break; // CMP (CMPU, extended) case 0xb3: output << Address_extended("CMPU"); break; // CMP (CMPU, extended)
// CMPS // CMPS
case 0x8c: output << AM_immediate_word("CMPS"); break; // CMP (CMPS, immediate) case 0x8c: output << AM_immediate_word("CMPS"); break; // CMP (CMPS, immediate)
case 0x9c: output << Address_direct("CMPS"); break; // CMP (CMPS, direct) case 0x9c: output << Address_direct("CMPS"); break; // CMP (CMPS, direct)
case 0xac: output << Address_indexed("CMPS"); break; // CMP (CMPS, indexed) case 0xac: output << Address_indexed("CMPS"); break; // CMP (CMPS, indexed)
case 0xbc: output << Address_extended("CMPS"); break; // CMP (CMPS, extended) case 0xbc: output << Address_extended("CMPS"); break; // CMP (CMPS, extended)

View File

@ -21,11 +21,14 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="..\inc\Disassembly.h" /> <ClInclude Include="..\inc\Disassembly.h" />
<ClInclude Include="..\inc\mc6809.h" /> <ClInclude Include="..\inc\mc6809.h" />
<ClInclude Include="..\inc\ProfileLineEventArgs.h" />
<ClInclude Include="..\inc\Profiler.h" />
<ClInclude Include="stdafx.h" /> <ClInclude Include="stdafx.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Disassembly.cpp" /> <ClCompile Include="Disassembly.cpp" />
<ClCompile Include="mc6809.cpp" /> <ClCompile Include="mc6809.cpp" />
<ClCompile Include="Profiler.cpp" />
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

View File

@ -20,6 +20,12 @@
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\inc\ProfileLineEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\Profiler.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">
@ -31,5 +37,8 @@
<ClCompile Include="Disassembly.cpp"> <ClCompile Include="Disassembly.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Profiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

41
MC6809/src/Profiler.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "stdafx.h"
#include "Profiler.h"
#include "Disassembly.h"
EightBit::Profiler::Profiler(mc6809& targetProcessor, Disassembly& disassemblerTarget)
: processor(targetProcessor),
disassembler(disassemblerTarget) {
instructionCounts.fill(0);
addressProfiles.fill(0);
addressCounts.fill(0);
}
void EightBit::Profiler::Generate() {
StartingOutput.fire();
EmitProfileInformation();
StartingOutput.fire();
}
void EightBit::Profiler::EmitProfileInformation() {
// For each memory address
for (int address = 0; address < 0x10000; ++address) {
// If there are any cycles associated
auto cycles = addressProfiles[address];
if (cycles > 0) {
// Dump a profile/disassembly line
auto source = disassembler.disassemble(address);
ProfileLineEventArgs event(address, source, cycles);
EmitLine.fire(event);
}
}
}
void EightBit::Profiler::addInstruction(uint8_t instruction) {
++instructionCounts[instruction];
}
void EightBit::Profiler::addAddress(uint16_t address, int cycles) {
addressCounts[address]++;
addressProfiles[address] += cycles;
}

View File

@ -27,6 +27,14 @@ void Board::raisePOWER() {
} }
void Board::lowerPOWER() { void Board::lowerPOWER() {
if (m_configuration.isProfileMode()) {
m_profiler.EmitLine.connect([this](EightBit::ProfileLineEventArgs line) {
std::cout << EightBit::Disassembly::dump_WordValue(line.address()) << " " << line.source() << std::endl;
});
m_profiler.Generate();
}
ACIA().lowerPOWER(); ACIA().lowerPOWER();
CPU().lowerPOWER(); CPU().lowerPOWER();
EightBit::Bus::lowerPOWER(); EightBit::Bus::lowerPOWER();
@ -71,6 +79,15 @@ void Board::initialise() {
} }
}); });
if (m_configuration.isProfileMode()) {
m_cpu.ExecutingInstruction.connect([this](EightBit::mc6809& cpu) {
m_profiler.addInstruction(peek(cpu.PC()));
});
m_cpu.ExecutedInstruction.connect([this](EightBit::mc6809& cpu) {
m_profiler.addAddress(cpu.PC().word, cpu.cycles());
});
}
if (m_configuration.isDebugMode()) { if (m_configuration.isDebugMode()) {
// MC6809 disassembly wiring // MC6809 disassembly wiring
CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) { CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) {

View File

@ -11,6 +11,7 @@
#include <Disassembly.h> #include <Disassembly.h>
#include <MC6850.h> #include <MC6850.h>
#include <UnusedMemory.h> #include <UnusedMemory.h>
#include <Profiler.h>
class Board : public EightBit::Bus { class Board : public EightBit::Bus {
public: public:
@ -38,6 +39,7 @@ private:
EightBit::mc6809 m_cpu = *this; EightBit::mc6809 m_cpu = *this;
EightBit::Disassembly m_disassembler = { *this, m_cpu }; EightBit::Disassembly m_disassembler = { *this, m_cpu };
EightBit::Profiler m_profiler = { m_cpu, m_disassembler };
uint64_t m_totalCycleCount = 0UL; uint64_t m_totalCycleCount = 0UL;
int64_t m_frameCycleCount = 0L; int64_t m_frameCycleCount = 0L;

View File

@ -14,6 +14,9 @@ public:
bool isDebugMode() const { return m_debugMode; } bool isDebugMode() const { return m_debugMode; }
void setDebugMode(bool value) { m_debugMode = value; } void setDebugMode(bool value) { m_debugMode = value; }
bool isProfileMode() const { return m_profileMode; }
void setProfileMode(bool value) { m_profileMode = value; }
bool terminatesEarly() const { return m_terminatesEarly; } bool terminatesEarly() const { return m_terminatesEarly; }
void setTerminatesEarly(bool value) { m_terminatesEarly = value; } void setTerminatesEarly(bool value) { m_terminatesEarly = value; }
@ -21,6 +24,7 @@ public:
private: private:
bool m_debugMode = false; bool m_debugMode = false;
bool m_profileMode = false;
bool m_terminatesEarly = false; bool m_terminatesEarly = false;
std::string m_romDirectory = "roms\\searle"; std::string m_romDirectory = "roms\\searle";
}; };

View File

@ -25,20 +25,17 @@ void Board::lowerPOWER() {
} }
void Board::initialise() { void Board::initialise() {
//CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); CPU().ExecutingInstruction.connect([this](EightBit::mc6809& cpu) {
//CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Debug, this, std::placeholders::_1)); m_disassembleAt = CPU().PC();
m_ignoreDisassembly = m_disassembler.ignore();
});
CPU().ExecutedInstruction.connect([this](EightBit::mc6809& cpu) {
if (!m_ignoreDisassembly)
std::cout << m_disassembler.trace(m_disassembleAt) << " " << std::endl;
});
} }
EightBit::MemoryMapping Board::mapping(uint16_t) { EightBit::MemoryMapping Board::mapping(uint16_t) {
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite }; return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
} }
void Board::Cpu_ExecutingInstruction_Debug(EightBit::mc6809&) {
m_disassembleAt = CPU().PC();
m_ignoreDisassembly = m_disassembler.ignore();
}
void Board::Cpu_ExecutedInstruction_Debug(EightBit::mc6809&) {
if (!m_ignoreDisassembly)
std::cout << m_disassembler.trace(m_disassembleAt) << " " << std::endl;
}

View File

@ -5,19 +5,19 @@
#include <mc6809.h> #include <mc6809.h>
#include <Disassembly.h> #include <Disassembly.h>
class Board : public EightBit::Bus { class Board final : public EightBit::Bus {
public: public:
Board(); Board();
EightBit::mc6809& CPU() { return m_cpu; } EightBit::mc6809& CPU() { return m_cpu; }
virtual void raisePOWER() final; void raisePOWER() final;
virtual void lowerPOWER() final; void lowerPOWER() final;
protected: protected:
virtual void initialise() final; void initialise() final;
virtual EightBit::MemoryMapping mapping(uint16_t address) final; EightBit::MemoryMapping mapping(uint16_t address) final;
private: private:
EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM
@ -27,7 +27,4 @@ private:
// The m_disassembleAt and m_ignoreDisassembly are used to skip pin events // The m_disassembleAt and m_ignoreDisassembly are used to skip pin events
EightBit::register16_t m_disassembleAt = 0x0000; EightBit::register16_t m_disassembleAt = 0x0000;
bool m_ignoreDisassembly = false; bool m_ignoreDisassembly = false;
void Cpu_ExecutingInstruction_Debug(EightBit::mc6809&);
void Cpu_ExecutedInstruction_Debug(EightBit::mc6809&);
}; };

View File

@ -10,42 +10,42 @@ namespace EightBit {
public: public:
mc6850(); mc6850();
// +--------+----------------------------------------------------------------------------------+ // +--------+----------------------------------------------------------------------------------+
// | | Buffer address | // | | Buffer address |
// | +------------------+------------------+--------------------+-----------------------+ // | +------------------+------------------+--------------------+-----------------------+
// | | _ | _ | _ | _ | // | | _ | _ | _ | _ |
// | Data | RS * R/W | RS * R/W | RS * R/W | RS * R/W | // | Data | RS * R/W | RS * R/W | RS * R/W | RS * R/W |
// | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) | // | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
// | Line | Transmit | Receive | | | // | Line | Transmit | Receive | | |
// | Number | Data | Data | Control | Status | // | Number | Data | Data | Control | Status |
// | | Register | Register | register | register | // | | Register | Register | Register | register |
// | +------------------+------------------+--------------------+-----------------------+ // | +------------------+------------------+--------------------+-----------------------+
// | | (Write only) + (Read only) + (Write only) | (Read only) | // | | (Write only) | (Read only) | (Write only) | (Read only) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register | // | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
// | | | | select 1 (CR0) | full (RDRF) | // | | | | select 1 (CR0) | full (RDRF) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 1 | Data bit 1 | Data bit 1 | Counter divide | Transmit data register| // | 1 | Data bit 1 | Data bit 1 | Counter divide | Transmit data register|
// | | | | select 2 (CR1) | empty (TDRE) | // | | | | select 2 (CR1) | empty (TDRE) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 2 | Data bit 2 | Data bit 2 | Word select 1 | Data carrier detect | // | 2 | Data bit 2 | Data bit 2 | Word select 1 | Data carrier detect |
// | | | | (CR2) | (DCD active) | // | | | | (CR2) | (DCD active) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 3 | Data bit 3 | Data bit 3 | Word select 1 | Clear to send | // | 3 | Data bit 3 | Data bit 3 | Word select 1 | Clear to send |
// | | | | (CR3) | (CTS active) | // | | | | (CR3) | (CTS active) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 4 | Data bit 4 | Data bit 4 | Word select 1 | Framing error | // | 4 | Data bit 4 | Data bit 4 | Word select 1 | Framing error |
// | | | | (CR4) | (FE) | // | | | | (CR4) | (FE) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 5 | Data bit 5 | Data bit 5 | Transmit control 1 | Receiver overrun | // | 5 | Data bit 5 | Data bit 5 | Transmit control 1 | Receiver overrun |
// | | | | (CR5) | (OVRN) | // | | | | (CR5) | (OVRN) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 6 | Data bit 6 | Data bit 6 | Transmit control 2 | Parity error (PE) | // | 6 | Data bit 6 | Data bit 6 | Transmit control 2 | Parity error (PE) |
// | | | | (CR6) | | // | | | | (CR6) | |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// | 7 | Data bit 7*** | Data bit 7** | Receive interrupt | Interrupt request | // | 7 | Data bit 7*** | Data bit 7** | Receive interrupt | Interrupt request |
// | | | | enable (CR7) | (IRQ active) | // | | | | enable (CR7) | (IRQ active) |
// +--------+------------------+------------------+--------------------+-----------------------+ // +--------+------------------+------------------+--------------------+-----------------------+
// * Leading bit = LSB = Bit 0 // * Leading bit = LSB = Bit 0
// ** Data bit will be zero in 7-bit plus parity modes // ** Data bit will be zero in 7-bit plus parity modes
// *** Data bit is "don't care" in 7-bit plus parity modes // *** Data bit is "don't care" in 7-bit plus parity modes
@ -84,7 +84,7 @@ namespace EightBit {
// CR5 and CR6 // CR5 and CR6
enum TransmitterControl { enum TransmitterControl {
ReadyLowInterruptDisabled = 0b00, ReadyLowInterruptDisabled = 0b00,
ReadyLowInterruptEnabled = 0b01, ReadyLowInterruptEnabled = 0b01,
ReadyHighInterruptDisabled = 0b10, ReadyHighInterruptDisabled = 0b10,
ReadyLowInterruptDisabledTransmitBreak = 0b11, ReadyLowInterruptDisabledTransmitBreak = 0b11,
}; };
@ -284,10 +284,10 @@ namespace EightBit {
bool m_statusRead = false; bool m_statusRead = false;
// Control registers // Control registers
CounterDivideSelect m_counterDivide = One; CounterDivideSelect m_counterDivide = CounterDivideSelect::One;
WordSelect m_wordSelect = SevenEvenTwo; WordSelect m_wordSelect = WordSelect::SevenEvenTwo;
TransmitterControl m_transmitControl = ReadyLowInterruptDisabled; TransmitterControl m_transmitControl = TransmitterControl::ReadyLowInterruptDisabled;
ReceiveControl m_receiveControl = ReceiveInterruptDisable; ReceiveControl m_receiveControl = ReceiveControl::ReceiveInterruptDisable;
// Status registers // Status registers
bool m_statusRDRF = false; bool m_statusRDRF = false;

Binary file not shown.

View File

@ -15,7 +15,7 @@ namespace EightBit {
static std::string state(Z80& cpu); static std::string state(Z80& cpu);
std::string disassemble(Z80& cpu); std::string disassemble(Z80& cpu);
static std::string flag(uint8_t value, int flag, const std::string& represents); static std::string flag(uint8_t value, int flag, std::string represents);
static std::string flags(uint8_t value); static std::string flags(uint8_t value);
static std::string hex(uint8_t value); static std::string hex(uint8_t value);
static std::string hex(uint16_t value); static std::string hex(uint16_t value);

View File

@ -726,7 +726,7 @@ void EightBit::Disassembler::disassembleOther(
} }
} }
std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string& represents) { std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string represents) {
std::ostringstream output; std::ostringstream output;
output << (value & flag ? represents : "-"); output << (value & flag ? represents : "-");
return output.str(); return output.str();

View File

@ -103,7 +103,7 @@ namespace EightBit {
virtual ~Device() = default; virtual ~Device() = default;
[[nodiscard]] bool powered() noexcept { return raised(POWER()); } [[nodiscard]] bool powered() const noexcept { return raised(POWER()); }
DECLARE_PIN_INPUT(POWER) DECLARE_PIN_INPUT(POWER)