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 <map>
#include <memory>
#include <stdexcept>
#include <string>
#include <SDL.h>
#include <Device.h>
#include "GameController.h"
#include "SDLWrapper.h"
class Configuration;
namespace Gaming {
class GameController;
class Game : public EightBit::Device {
public:
Game();
@ -28,10 +29,10 @@ namespace Gaming {
virtual float fps() const = 0;
virtual bool useVsync() const = 0;
virtual int windowWidth() const noexcept { return displayWidth() * displayScale(); }
virtual int windowHeight() const noexcept { return displayHeight() * displayScale(); }
virtual int displayWidth() const noexcept { return rasterWidth(); }
virtual int displayHeight() const noexcept { return rasterHeight(); }
virtual int windowWidth() const noexcept;
virtual int windowHeight() const noexcept;
virtual int displayWidth() const noexcept;
virtual int displayHeight() const noexcept;
virtual int displayScale() const noexcept = 0;
virtual int rasterWidth() const noexcept = 0;
virtual int rasterHeight() const noexcept = 0;
@ -67,19 +68,8 @@ namespace Gaming {
void toggleFullscreen();
std::shared_ptr<GameController> 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 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;
}
std::shared_ptr<GameController> gameController(int which) const;
int mappedController(const SDL_JoystickID which) const;
int chooseControllerIndex(int who) const;
std::shared_ptr<GameController> chooseController(int who) const;

View File

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

View File

@ -1,12 +1,30 @@
#include "stdafx.h"
#include "Game.h"
#include "GameController.h"
namespace Gaming {
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() {
Device::raisePOWER();
@ -168,6 +186,20 @@ void Game::addJoystick(SDL_Event& e) {
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
int Game::chooseControllerIndex(const int who) const {
const auto count = m_gameControllers.size();

View File

@ -40,7 +40,7 @@ namespace EightBit {
Signal<EventArgs> MachineTicked;
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:
int execute() final;

View File

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

View File

@ -17,15 +17,15 @@ EightBit::Profiler::Profiler(MOS6502& targetProcessor, Disassembly& disassembler
}
void EightBit::Profiler::Generate() {
StartingOutput.fire(EventArgs::empty());
StartingOutput.fire();
EmitProfileInformation();
StartingOutput.fire(EventArgs::empty());
StartingOutput.fire();
}
void EightBit::Profiler::EmitProfileInformation() {
{
StartingLineOutput.fire(EventArgs::empty());
StartingLineOutput.fire();
// For each memory address
for (int address = 0; address < 0x10000; ++address) {
// If there are any cycles associated
@ -37,11 +37,11 @@ void EightBit::Profiler::EmitProfileInformation() {
EmitLine.fire(event);
}
}
FinishedLineOutput.fire(EventArgs::empty());
FinishedLineOutput.fire();
}
{
StartingScopeOutput.fire(EventArgs::empty());
StartingScopeOutput.fire();
for (auto& scopeCycle : scopeCycles) {
auto name = scopeCycle.first;
auto cycles = scopeCycle.second;
@ -50,7 +50,7 @@ void EightBit::Profiler::EmitProfileInformation() {
ProfileScopeEventArgs event(name, cycles, count);
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 0x06: memoryReadModifyWrite(asl(AM_ZeroPage())); break; // ASL (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 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 0x0d: A() = orr(A(), AM_Absolute()); break; // ORA (absolute)
case 0x0e: memoryReadModifyWrite(asl(AM_Absolute())); break; // ASL (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 0x12: break;
case 0x13: slo(AM_IndirectIndexedY()); break; // *SLO (indirect indexed Y)
case 0x14: AM_ZeroPageX(); break; // *NOP (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 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 0x19: A() = orr(A(), AM_AbsoluteY()); break; // ORA (absolute, Y)
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 0x1d: A() = orr(A(), AM_AbsoluteX()); break; // ORA (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 0x21: A() = andr(A(), AM_IndexedIndirectX()); break; // AND (indexed indirect X)
case 0x22: break;
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 0x26: memoryReadModifyWrite(rol(AM_ZeroPage())); break; // ROL (zero page)
case 0x27: rla(AM_ZeroPage()); break; // *RLA (zero page)
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 0x2b: anc(AM_Immediate()); break; // *ANC (immediate)
case 0x2c: bit(A(), AM_Absolute()); break; // BIT (absolute)
case 0x2b: anc(AM_Immediate()); break; // *ANC (immediate)
case 0x2c: bit(A(), AM_Absolute()); break; // BIT (absolute)
case 0x2d: A() = andr(A(), AM_Absolute()); break; // AND (absolute)
case 0x2e: memoryReadModifyWrite(rol(AM_Absolute())); break; // ROL (absolute)
case 0x2f: rla(AM_Absolute()); break; // *RLA (absolute)
@ -168,19 +168,19 @@ int EightBit::MOS6502::execute() {
case 0x32: break;
case 0x33: rla(AM_IndirectIndexedY()); break; // *RLA (indirect indexed Y)
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 0x37: rla(AM_ZeroPageX()); break; // *RLA (zero page, X)
case 0x38: memoryRead(); P() = setBit(P(), CF); break; // SEC (implied)
case 0x39: A() = andr(A(), AM_AbsoluteY()); break; // AND (absolute, Y)
case 0x37: rla(AM_ZeroPageX()); break; // *RLA (zero page, X)
case 0x38: memoryRead(); P() = setBit(P(), CF); break; // SEC (implied)
case 0x39: A() = andr(A(), AM_AbsoluteY()); break; // AND (absolute, Y)
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 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 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 0x42: break;
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 0x46: memoryReadModifyWrite(lsr(AM_ZeroPage())); break; // LSR (zero page)
case 0x47: sre(AM_ZeroPage()); break; // *SRE (zero page)
case 0x48: memoryRead(); push(A()); break; // PHA (implied)
case 0x49: A() = eorr(A(), AM_Immediate()); break; // EOR (immediate)
case 0x48: memoryRead(); push(A()); break; // PHA (implied)
case 0x49: A() = eorr(A(), AM_Immediate()); break; // EOR (immediate)
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 0x4d: A() = eorr(A(), AM_Absolute()); break; // EOR (absolute)
case 0x4e: memoryReadModifyWrite(lsr(AM_Absolute())); break; // LSR (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 0x52: break;
case 0x53: sre(AM_IndirectIndexedY()); break; // *SRE (indirect indexed Y)
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 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 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 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 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 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 0x62: break;
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 0x69: A() = adc(A(), AM_Immediate()); break; // ADC (immediate)
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 0x6d: A() = adc(A(), AM_Absolute()); break; // ADC (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 0x75: A() = adc(A(), AM_ZeroPageX()); break; // ADC (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 0x78: memoryRead(); P() = setBit(P(), IF); break; // SEI (implied)
case 0x77: rra(AM_ZeroPageX()); break; // *RRA (zero page, X)
case 0x78: memoryRead(); P() = setBit(P(), IF); break; // SEI (implied)
case 0x79: A() = adc(A(), AM_AbsoluteY()); break; // ADC (absolute, Y)
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 0x7d: A() = adc(A(), AM_AbsoluteX()); break; // ADC (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 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 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 0x93: break;
case 0x94: memoryWrite(Address_ZeroPageX(), Y()); break; // STY (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 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 0x99: sta_AbsoluteY(); break; // STA (absolute, Y)
case 0x9a: memoryRead(); S() = X(); break; // TXS (implied)
case 0x99: sta_AbsoluteY(); break; // STA (absolute, Y)
case 0x9a: memoryRead(); S() = X(); break; // TXS (implied)
case 0x9b: break;
case 0x9c: break;
case 0x9d: sta_AbsoluteX(); break; // STA (absolute, X)
case 0x9d: sta_AbsoluteX(); break; // STA (absolute, X)
case 0x9e: break;
case 0x9f: break;
@ -293,20 +293,20 @@ int EightBit::MOS6502::execute() {
case 0xa8: memoryRead(); Y() = through(A()); break; // TAY (implied)
case 0xa9: A() = through(AM_Immediate()); break; // LDA (immediate)
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 0xad: A() = through(AM_Absolute()); break; // LDA (absolute)
case 0xae: X() = through(AM_Absolute()); break; // LDX (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 0xb2: break;
case 0xb3: A() = X() = through(AM_IndirectIndexedY()); break; // *LAX (indirect indexed Y)
case 0xb4: Y() = through(AM_ZeroPageX()); break; // LDY (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 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 0xb9: A() = through(AM_AbsoluteY()); break; // LDA (absolute, Y)
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 0xbd: A() = through(AM_AbsoluteX()); break; // LDA (absolute, X)
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 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 0xc3: dcp(AM_IndexedIndirectX()); break; // *DCP (indexed indirect X)
case 0xc4: cmp(Y(), AM_ZeroPage()); break; // CPY (zero page)
case 0xc5: cmp(A(), AM_ZeroPage()); break; // CMP (zero page)
case 0xc4: cmp(Y(), AM_ZeroPage()); break; // CPY (zero page)
case 0xc5: cmp(A(), AM_ZeroPage()); break; // CMP (zero page)
case 0xc6: memoryReadModifyWrite(dec(AM_ZeroPage())); break; // DEC (zero page)
case 0xc7: dcp(AM_ZeroPage()); break; // *DCP (zero page)
case 0xc8: memoryRead(); Y() = inc(Y()); break; // INY (implied)
case 0xc9: cmp(A(), AM_Immediate()); break; // CMP (immediate)
case 0xca: memoryRead(); X() = dec(X()); break; // DEX (implied)
case 0xcb: axs(AM_Immediate()); break; // *AXS (immediate)
case 0xcc: cmp(Y(), AM_Absolute()); break; // CPY (absolute)
case 0xcd: cmp(A(), AM_Absolute()); break; // CMP (absolute)
case 0xcb: axs(AM_Immediate()); break; // *AXS (immediate)
case 0xcc: cmp(Y(), AM_Absolute()); break; // CPY (absolute)
case 0xcd: cmp(A(), AM_Absolute()); break; // CMP (absolute)
case 0xce: memoryReadModifyWrite(dec(AM_Absolute())); break; // DEC (absolute)
case 0xcf: dcp(AM_Absolute()); break; // *DCP (absolute)
case 0xd0: branch(!zero()); break; // BNE (relative)
case 0xd1: cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y)
case 0xd0: branch(!zero()); break; // BNE (relative)
case 0xd1: cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y)
case 0xd2: break;
case 0xd3: dcp(AM_IndirectIndexedY()); break; // *DCP (indirect indexed Y)
case 0xd4: AM_ZeroPageX(); break; // *NOP (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 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 0xd9: cmp(A(), AM_AbsoluteY()); break; // CMP (absolute, Y)
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 0xdd: cmp(A(), AM_AbsoluteX()); break; // CMP (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 0xe1: A() = sbc(A(), AM_IndexedIndirectX()); break; // SBC (indexed indirect X)
case 0xe2: AM_Immediate(); break; // *NOP (immediate)
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 0xe6: memoryReadModifyWrite(inc(AM_ZeroPage())); break; // INC (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 0xea: memoryRead(); break; // NOP (implied)
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 0xee: memoryReadModifyWrite(inc(AM_Absolute())); break; // INC (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 0xf5: A() = sbc(A(), AM_ZeroPageX()); break; // SBC (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 0xf8: memoryRead(); P() = setBit(P(), DF); break; // SED (implied)
case 0xf7: isb(AM_ZeroPageX()); break; // *ISB (zero page, X)
case 0xf8: memoryRead(); P() = setBit(P(), DF); break; // SED (implied)
case 0xf9: A() = sbc(A(), AM_AbsoluteY()); break; // SBC (absolute, Y)
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 0xfd: A() = sbc(A(), AM_AbsoluteX()); break; // SBC (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);

View File

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

View File

@ -12,11 +12,24 @@ namespace EightBit {
public:
Disassembly(Bus& bus, mc6809& processor);
bool ignore();
[[nodiscard]] bool ignore();
std::string trace(uint16_t current);
std::string trace(register16_t current);
std::string trace();
[[nodiscard]] std::string trace(uint16_t current);
[[nodiscard]] std::string disassemble(uint16_t current);
[[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:
Bus& m_bus;
@ -27,63 +40,50 @@ namespace EightBit {
bool m_prefix10 = 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);
mc6809& CPU() { return m_cpu; }
[[nodiscard]] mc6809& CPU() { return m_cpu; }
[[nodiscard]] Bus& BUS() { return m_bus; }
uint8_t getByte(uint16_t address);
uint16_t getWord(uint16_t address);
[[nodiscard]] uint8_t getByte(uint16_t address);
[[nodiscard]] uint16_t getWord(uint16_t address);
std::string disassembleUnprefixed();
std::string disassemble10();
std::string disassemble11();
[[nodiscard]] std::string disassembleUnprefixed();
[[nodiscard]] std::string disassemble10();
[[nodiscard]] std::string disassemble11();
//
std::string RR(int which);
std::string wrapIndirect(std::string what, bool indirect);
[[nodiscard]] std::string RR(int which);
[[nodiscard]] std::string wrapIndirect(std::string what, bool indirect);
std::string Address_direct(std::string mnemomic);
std::string Address_indexed(std::string mnemomic);
std::string Address_extended(std::string mnemomic);
std::string Address_relative_byte(std::string mnemomic);
std::string Address_relative_word(std::string mnemomic);
[[nodiscard]] std::string Address_direct(std::string mnemomic);
[[nodiscard]] std::string Address_indexed(std::string mnemomic);
[[nodiscard]] std::string Address_extended(std::string mnemomic);
[[nodiscard]] std::string Address_relative_byte(std::string mnemomic);
[[nodiscard]] std::string Address_relative_word(std::string mnemomic);
std::string AM_immediate_byte(std::string mnemomic);
std::string AM_immediate_word(std::string mnemomic);
[[nodiscard]] std::string AM_immediate_byte(std::string mnemomic);
[[nodiscard]] std::string AM_immediate_word(std::string mnemomic);
//
std::string branchShort(std::string mnemomic);
std::string branchLong(std::string mnemomic);
[[nodiscard]] std::string branchShort(std::string mnemomic);
[[nodiscard]] std::string branchLong(std::string mnemomic);
//
std::string referenceTransfer8(int specifier);
std::string referenceTransfer16(int specifier);
std::string tfr(std::string mnemomic);
[[nodiscard]] std::string referenceTransfer8(int specifier);
[[nodiscard]] std::string referenceTransfer16(int specifier);
[[nodiscard]] std::string tfr(std::string mnemomic);
//
std::string pulS();
std::string pulU();
std::string pshS();
std::string pshU();
std::string pulX(std::string mnemomic, std::string upon);
std::string pshX(std::string mnemomic, std::string upon);
Bus& BUS() { return m_bus; }
[[nodiscard]] std::string pulS();
[[nodiscard]] std::string pulU();
[[nodiscard]] std::string pshS();
[[nodiscard]] std::string pshU();
[[nodiscard]] std::string pulX(std::string mnemomic, std::string upon);
[[nodiscard]] std::string pshX(std::string mnemomic, std::string upon);
};
}

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)
// 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 0xa9: output << Address_indexed("ADCA"); break; // ADC (ADCA indexed)
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 0xe9: output << Address_indexed("ADCB"); break; // ADC (ADCB indexed)
case 0xf9: output << Address_extended("ADCB"); break; // ADC (ADCB extended)
// ADD
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 0xbb: output << Address_extended("ADDA"); break; // ADD (ADDA extended)
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 0xfb: output << Address_extended("ADDB"); break; // ADD (ADDB extended)
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 0xf3: output << Address_extended("ADDD"); break; // ADD (ADDD extended)
// 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 0xa4: output << Address_indexed("ANDA"); break; // AND (ANDA indexed)
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 0xe4: output << Address_indexed("ANDB"); break; // AND (ANDB indexed)
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)
// 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 0x58: output << "\tASLB\t"; break; // ASL (ASLB inherent)
case 0x68: output << Address_indexed("ASL"); break; // ASL (indexed)
case 0x78: output << Address_extended("ASL"); break; // ASL (extended)
// 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 0x57: output << "\tASRB\t"; break; // ASR (ASRB inherent)
case 0x67: output << Address_indexed("ASR"); break; // ASR (indexed)
case 0x77: output << Address_extended("ASR"); break; // ASR (extended)
// 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 0xa5: output << Address_indexed("BITA"); break; // BIT (BITA indexed)
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 0xe5: output << Address_indexed("BITB"); break; // BIT (BITB indexed)
case 0xf5: output << Address_extended("BITB"); break; // BIT (BITB extended)
// 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 0x5f: output << "\tCLRB\t"; break; // CLR (CLRB implied)
case 0x6f: output << Address_indexed("CLR"); break; // CLR (indexed)
@ -220,25 +220,25 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
// CMP
// 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 0xa1: output << Address_indexed("CMPA"); break; // CMP (CMPA, indexed)
case 0xb1: output << Address_extended("CMPA"); break; // CMP (CMPA, extended)
// 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 0xe1: output << Address_indexed("CMPB"); break; // CMP (CMPB, indexed)
case 0xf1: output << Address_extended("CMPB"); break; // CMP (CMPB, extended)
// 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 0xac: output << Address_indexed("CMPX"); break; // CMP (CMPX, indexed)
case 0xbc: output << Address_extended("CMPX"); break; // CMP (CMPX, extended)
// 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 0x53: output << "\tCOMB\t"; break; // COM (COMB inherent)
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)
// 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 0x5a: output << "\tDECB\t"; break; // DEC (DECB inherent)
case 0x6a: output << Address_indexed("DEC"); break; // DEC (indexed)
@ -260,13 +260,13 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
// EOR
// 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 0xa8: output << Address_indexed("EORA"); break; // EOR (EORA indexed)
case 0xb8: output << Address_extended("EORA"); break; // EOR (EORA extended)
// 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 0xe8: output << Address_indexed("EORB"); break; // EOR (EORB indexed)
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)
// 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 0x5c: output << "\tINCB\t";; break; // INC (INCB inherent)
case 0x6c: output << Address_indexed("INC"); break; // INC (indexed)
case 0x7c: output << Address_extended("INC"); break; // INC (extended)
// 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 0x7e: output << Address_extended("JMP"); break; // JMP (extended)
// 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 0xbd: output << Address_extended("JSR"); break; // JSR (extended)
@ -295,31 +295,31 @@ std::string EightBit::Disassembly::disassembleUnprefixed() {
// LDA
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 0xb6: output << Address_extended("LDA"); break; // LD (LDA extended)
// LDB
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 0xf6: output << Address_extended("LDB"); break; // LD (LDB extended)
// LDD
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 0xfc: output << Address_extended("LDD"); break; // LD (LDD extended)
// LDU
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 0xfe: output << Address_extended("LDU"); break; // LD (LDU extended)
// LDX
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 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)
// 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 0x54: output << "\tLSRB\t"; break; // LSR (LSRB inherent)
case 0x64: output << Address_indexed("LSR"); break; // LSR (indexed)
case 0x74: output << Address_extended("LSR"); break; // LSR (extended)
// MUL
case 0x3d: output << "\tMUL\t"; break; // MUL (inherent)
case 0x3d: output << "\tMUL\t"; break; // MUL (inherent)
// 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 0x50: output << "\tNEGB\t"; break; // NEG (NEGB, inherent)
case 0x60: output << Address_indexed("NEG"); break; // NEG (indexed)
case 0x70: output << Address_extended("NEG"); break; // NEG (extended)
// NOP
case 0x12: output << "\tNOP\t"; break; // NOP (inherent)
case 0x12: output << "\tNOP\t"; break; // NOP (inherent)
// OR
// ORA
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 0xba: output << Address_extended("ORA"); break; // OR (ORA extended)
// ORB
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 0xfa: output << Address_extended("ORB"); break; // OR (ORB extended)
// ORCC
case 0x1a: output << AM_immediate_byte("ORCC"); break; // OR (ORCC immediate)
case 0x1a: output << AM_immediate_byte("ORCC"); break; // OR (ORCC immediate)
// PSH
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)
// 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 0x59: output << "\tROLB\t"; break; // ROL (ROLB inherent)
case 0x69: output << Address_indexed("ROL"); break; // ROL (indexed)
case 0x79: output << Address_extended("ROL"); break; // ROL (extended)
// 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 0x56: output << "\tRORB\t"; break; // ROR (RORB inherent)
case 0x66: output << Address_indexed("ROR"); break; // ROR (indexed)
case 0x76: output << Address_extended("ROR"); break; // ROR (extended)
// RTI
case 0x3B: output << "\tRTI\t"; break; // RTI (inherent)
case 0x3B: output << "\tRTI\t"; break; // RTI (inherent)
// RTS
case 0x39: output << "\tRTS\t"; break; // RTS (inherent)
case 0x39: output << "\tRTS\t"; break; // RTS (inherent)
// SBC
// 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 0xa2: output << Address_indexed("SBCA"); break; // SBC (SBCA indexed)
case 0xb2: output << Address_extended("SBCA"); break; // SBC (SBCA extended)
// 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 0xe2: output << Address_indexed("SBCB"); break; // SBC (SBCB indexed)
case 0xf2: output << Address_extended("SBCB"); break; // SBC (SBCB extended)
// SEX
case 0x1d: output << "\tSEX\t"; break; // SEX (inherent)
case 0x1d: output << "\tSEX\t"; break; // SEX (inherent)
// ST
// 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 0xb7: output << Address_extended("STA"); break; // ST (STA extended)
// 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 0xf7: output << Address_extended("STB"); break; // ST (STB extended)
// 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 0xfd: output << Address_extended("STD"); break; // ST (STD extended)
// 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 0xff: output << Address_extended("STU"); break; // ST (STU extended)
// 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 0xbf: output << Address_extended("STX"); break; // ST (STX extended)
// SUB
// 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 0xa0: output << Address_indexed("SUBA"); break; // SUB (SUBA indexed)
case 0xb0: output << Address_extended("SUBA"); break; // SUB (SUBA extended)
// 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 0xe0: output << Address_indexed("SUBB"); break; // SUB (SUBB indexed)
case 0xf0: output << Address_extended("SUBB"); break; // SUB (SUBB extended)
// 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 0xa3: output << Address_indexed("SUBD"); break; // SUB (SUBD indexed)
case 0xb3: output << Address_extended("SUBD"); break; // SUB (SUBD extended)
// SWI
case 0x3f: output << "\tSWI\t"; break; // SWI (inherent)
case 0x3f: output << "\tSWI\t"; break; // SWI (inherent)
// SYNC
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)
// 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 0x5d: output << "\tTSTB\t"; break; // TST (TSTB inherent)
case 0x6d: output << Address_indexed("TST"); break; // TST (indexed)
@ -516,13 +516,13 @@ std::string EightBit::Disassembly::disassemble10() {
// CMP
// 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 0xa3: output << Address_indexed("CMPD"); break; // CMP (CMPD, indexed)
case 0xb3: output << Address_extended("CMPD"); break; // CMP (CMPD, extended)
// 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 0xac: output << Address_indexed("CMPY"); break; // CMP (CMPY, indexed)
case 0xbc: output << Address_extended("CMPY"); break; // CMP (CMPY, extended)
@ -531,13 +531,13 @@ std::string EightBit::Disassembly::disassemble10() {
// LDS
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 0xfe: output << Address_extended("LDS"); break; // LD (LDS extended)
// LDY
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 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)
// 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 0xff: output << Address_extended("STS"); break; // ST (STS extended)
@ -593,13 +593,13 @@ std::string EightBit::Disassembly::disassemble11() {
// CMP
// 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 0xa3: output << Address_indexed("CMPU"); break; // CMP (CMPU, indexed)
case 0xb3: output << Address_extended("CMPU"); break; // CMP (CMPU, extended)
// 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 0xac: output << Address_indexed("CMPS"); break; // CMP (CMPS, indexed)
case 0xbc: output << Address_extended("CMPS"); break; // CMP (CMPS, extended)

View File

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

View File

@ -20,6 +20,12 @@
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\ProfileLineEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\Profiler.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -31,5 +37,8 @@
<ClCompile Include="Disassembly.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Profiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</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() {
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();
CPU().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()) {
// MC6809 disassembly wiring
CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) {

View File

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

View File

@ -14,6 +14,9 @@ public:
bool isDebugMode() const { return m_debugMode; }
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; }
void setTerminatesEarly(bool value) { m_terminatesEarly = value; }
@ -21,6 +24,7 @@ public:
private:
bool m_debugMode = false;
bool m_profileMode = false;
bool m_terminatesEarly = false;
std::string m_romDirectory = "roms\\searle";
};

View File

@ -25,20 +25,17 @@ void Board::lowerPOWER() {
}
void Board::initialise() {
//CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1));
//CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Debug, this, std::placeholders::_1));
CPU().ExecutingInstruction.connect([this](EightBit::mc6809& cpu) {
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) {
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 <Disassembly.h>
class Board : public EightBit::Bus {
class Board final : public EightBit::Bus {
public:
Board();
EightBit::mc6809& CPU() { return m_cpu; }
virtual void raisePOWER() final;
virtual void lowerPOWER() final;
void raisePOWER() final;
void lowerPOWER() final;
protected:
virtual void initialise() final;
void initialise() final;
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
EightBit::MemoryMapping mapping(uint16_t address) final;
private:
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
EightBit::register16_t m_disassembleAt = 0x0000;
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:
mc6850();
// +--------+----------------------------------------------------------------------------------+
// | | Buffer address |
// | +------------------+------------------+--------------------+-----------------------+
// | | _ | _ | _ | _ |
// | Data | RS * R/W | RS * R/W | RS * R/W | RS * R/W |
// | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
// | Line | Transmit | Receive | | |
// | Number | Data | Data | Control | Status |
// | | Register | Register | register | register |
// | +------------------+------------------+--------------------+-----------------------+
// | | (Write only) + (Read only) + (Write only) | (Read only) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
// | | | | select 1 (CR0) | full (RDRF) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 1 | Data bit 1 | Data bit 1 | Counter divide | Transmit data register|
// | | | | select 2 (CR1) | empty (TDRE) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 2 | Data bit 2 | Data bit 2 | Word select 1 | Data carrier detect |
// | | | | (CR2) | (DCD active) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 3 | Data bit 3 | Data bit 3 | Word select 1 | Clear to send |
// | | | | (CR3) | (CTS active) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 4 | Data bit 4 | Data bit 4 | Word select 1 | Framing error |
// | | | | (CR4) | (FE) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 5 | Data bit 5 | Data bit 5 | Transmit control 1 | Receiver overrun |
// | | | | (CR5) | (OVRN) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 6 | Data bit 6 | Data bit 6 | Transmit control 2 | Parity error (PE) |
// | | | | (CR6) | |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 7 | Data bit 7*** | Data bit 7** | Receive interrupt | Interrupt request |
// | | | | enable (CR7) | (IRQ active) |
// +--------+------------------+------------------+--------------------+-----------------------+
// +--------+----------------------------------------------------------------------------------+
// | | Buffer address |
// | +------------------+------------------+--------------------+-----------------------+
// | | _ | _ | _ | _ |
// | Data | RS * R/W | RS * R/W | RS * R/W | RS * R/W |
// | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
// | Line | Transmit | Receive | | |
// | Number | Data | Data | Control | Status |
// | | Register | Register | Register | register |
// | +------------------+------------------+--------------------+-----------------------+
// | | (Write only) | (Read only) | (Write only) | (Read only) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
// | | | | select 1 (CR0) | full (RDRF) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 1 | Data bit 1 | Data bit 1 | Counter divide | Transmit data register|
// | | | | select 2 (CR1) | empty (TDRE) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 2 | Data bit 2 | Data bit 2 | Word select 1 | Data carrier detect |
// | | | | (CR2) | (DCD active) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 3 | Data bit 3 | Data bit 3 | Word select 1 | Clear to send |
// | | | | (CR3) | (CTS active) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 4 | Data bit 4 | Data bit 4 | Word select 1 | Framing error |
// | | | | (CR4) | (FE) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 5 | Data bit 5 | Data bit 5 | Transmit control 1 | Receiver overrun |
// | | | | (CR5) | (OVRN) |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 6 | Data bit 6 | Data bit 6 | Transmit control 2 | Parity error (PE) |
// | | | | (CR6) | |
// +--------+------------------+------------------+--------------------+-----------------------+
// | 7 | Data bit 7*** | Data bit 7** | Receive interrupt | Interrupt request |
// | | | | enable (CR7) | (IRQ active) |
// +--------+------------------+------------------+--------------------+-----------------------+
// * Leading bit = LSB = Bit 0
// ** Data bit will be zero 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
enum TransmitterControl {
ReadyLowInterruptDisabled = 0b00,
ReadyLowInterruptEnabled = 0b01,
ReadyLowInterruptEnabled = 0b01,
ReadyHighInterruptDisabled = 0b10,
ReadyLowInterruptDisabledTransmitBreak = 0b11,
};
@ -284,10 +284,10 @@ namespace EightBit {
bool m_statusRead = false;
// Control registers
CounterDivideSelect m_counterDivide = One;
WordSelect m_wordSelect = SevenEvenTwo;
TransmitterControl m_transmitControl = ReadyLowInterruptDisabled;
ReceiveControl m_receiveControl = ReceiveInterruptDisable;
CounterDivideSelect m_counterDivide = CounterDivideSelect::One;
WordSelect m_wordSelect = WordSelect::SevenEvenTwo;
TransmitterControl m_transmitControl = TransmitterControl::ReadyLowInterruptDisabled;
ReceiveControl m_receiveControl = ReceiveControl::ReceiveInterruptDisable;
// Status registers
bool m_statusRDRF = false;

Binary file not shown.

View File

@ -15,7 +15,7 @@ namespace EightBit {
static std::string state(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 hex(uint8_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;
output << (value & flag ? represents : "-");
return output.str();

View File

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