Initial stab at getting MOS6502 imported to the EightBit library.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-07-02 22:03:33 +01:00
parent 6af1857cb0
commit 88d3e4fd47
30 changed files with 1370 additions and 1371 deletions

View File

@ -1,17 +0,0 @@
#pragma once
#include <cstdint>
class AddressEventArgs
{
private:
uint16_t m_address;
uint8_t m_cell;
public:
AddressEventArgs(uint16_t address, uint8_t cell)
: m_address(address), m_cell(cell) {}
uint16_t getAddress() const { return m_address; }
uint8_t getCell() const { return m_cell; }
};

View File

@ -1,21 +1,23 @@
#pragma once
enum AddressingMode {
Illegal,
Implied,
Accumulator,
Immediate,
Relative,
XIndexed,
IndexedY,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteY,
AbsoluteXIndirect,
Indirect,
ZeroPageIndirect,
ZeroPageRelative
};
namespace EightBit {
enum AddressingMode {
Illegal,
Implied,
Accumulator,
Immediate,
Relative,
XIndexed,
IndexedY,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteY,
AbsoluteXIndirect,
Indirect,
ZeroPageIndirect,
ZeroPageRelative
};
}

View File

@ -3,9 +3,12 @@
#include <cstdint>
#include <functional>
typedef std::function<std::string(uint16_t current)> dumper_t;
namespace EightBit {
struct AddressingModeDumper {
dumper_t byteDumper;
dumper_t disassemblyDumper;
};
typedef std::function<std::string(uint16_t current)> dumper_t;
struct AddressingModeDumper {
dumper_t byteDumper;
dumper_t disassemblyDumper;
};
}

View File

@ -3,62 +3,63 @@
#include <map>
#include <cstdint>
#include <mos6502.h>
#include <AddressingMode.h>
#include "mos6502.h"
#include "AddressingMode.h"
#include "Symbols.h"
#include "AddressingModeDumper.h"
class Disassembly
{
public:
MOS6502& processor;
const Symbols& symbols;
namespace EightBit {
class Disassembly {
public:
MOS6502& processor;
const Symbols& symbols;
std::map<AddressingMode, AddressingModeDumper> dumpers;
std::map<AddressingMode, AddressingModeDumper> dumpers;
Disassembly(MOS6502& processor, const Symbols& symbols);
Disassembly(MOS6502& processor, const Symbols& symbols);
std::string Dump_ByteValue(uint8_t value) const;
std::string Dump_WordValue(uint16_t value) const;
std::string Dump_ByteValue(uint8_t value) const;
std::string Dump_WordValue(uint16_t value) const;
std::string DumpBytes(AddressingMode mode, uint16_t current) const;
std::string Disassemble(uint16_t current) const;
std::string DumpOperand(AddressingMode mode, uint16_t current) const;
std::string DumpBytes(AddressingMode mode, uint16_t current) const;
std::string Disassemble(uint16_t current) const;
std::string DumpOperand(AddressingMode mode, uint16_t current) const;
private:
uint8_t GetByte(uint16_t address) const;
uint16_t GetWord(uint16_t address) const;
private:
uint8_t GetByte(uint16_t address) const;
uint16_t GetWord(uint16_t address) const;
std::string Dump_Nothing(uint16_t unused) const;
std::string Dump_Byte(uint16_t address) const;
std::string Dump_DByte(uint16_t address) const;
std::string Dump_Nothing(uint16_t unused) const;
std::string Dump_Byte(uint16_t address) const;
std::string Dump_DByte(uint16_t address) const;
std::string ConvertAddress(uint16_t address) const;
std::string ConvertAddress(uint8_t address) const;
std::string ConvertConstant(uint16_t constant) const;
std::string ConvertConstant(uint8_t constant) const;
std::string ConvertAddress(uint16_t address) const;
std::string ConvertAddress(uint8_t address) const;
std::string ConvertConstant(uint16_t constant) const;
std::string ConvertConstant(uint8_t constant) const;
std::string Dump_A(uint16_t unused) const;
std::string Dump_imm(uint16_t current) const;
std::string Dump_abs(uint16_t current) const;
std::string Dump_zp(uint16_t current) const;
std::string Dump_zpx(uint16_t current) const;
std::string Dump_zpy(uint16_t current) const;
std::string Dump_absx(uint16_t current) const;
std::string Dump_absy(uint16_t current) const;
std::string Dump_absxind(uint16_t current) const;
std::string Dump_xind(uint16_t current) const;
std::string Dump_indy(uint16_t current) const;
std::string Dump_ind(uint16_t current) const;
std::string Dump_zpind(uint16_t current) const;
std::string Dump_rel(uint16_t current) const;
std::string Dump_zprel(uint16_t current) const;
std::string Dump_A(uint16_t unused) const;
std::string Dump_imm(uint16_t current) const;
std::string Dump_abs(uint16_t current) const;
std::string Dump_zp(uint16_t current) const;
std::string Dump_zpx(uint16_t current) const;
std::string Dump_zpy(uint16_t current) const;
std::string Dump_absx(uint16_t current) const;
std::string Dump_absy(uint16_t current) const;
std::string Dump_absxind(uint16_t current) const;
std::string Dump_xind(uint16_t current) const;
std::string Dump_indy(uint16_t current) const;
std::string Dump_ind(uint16_t current) const;
std::string Dump_zpind(uint16_t current) const;
std::string Dump_rel(uint16_t current) const;
std::string Dump_zprel(uint16_t current) const;
const AddressingModeDumper& getDumper(AddressingMode mode) const {
auto dumper = dumpers.find(mode);
if (dumper == dumpers.end())
throw std::invalid_argument("Illegal addressing mode");
return dumper->second;
}
};
const AddressingModeDumper& getDumper(AddressingMode mode) const {
auto dumper = dumpers.find(mode);
if (dumper == dumpers.end())
throw std::invalid_argument("Illegal addressing mode");
return dumper->second;
}
};
}

View File

@ -2,14 +2,15 @@
#include <string>
class DisassemblyEventArgs
{
private:
std::string m_output;
namespace EightBit {
class DisassemblyEventArgs {
private:
std::string m_output;
public:
DisassemblyEventArgs(std::string output)
: m_output(output) {}
public:
DisassemblyEventArgs(std::string output)
: m_output(output) {}
const std::string& getOutput() const { return m_output; }
};
const std::string& getOutput() const { return m_output; }
};
}

View File

@ -1,76 +0,0 @@
#pragma once
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include "Signal.h"
#include "AddressEventArgs.h"
class Memory
{
private:
std::vector<uint8_t> memory;
std::vector<bool> locked;
public:
Memory(unsigned memorySize)
: memory(memorySize),
locked(memorySize) {}
Signal<AddressEventArgs> InvalidWriteAttempt;
Signal<AddressEventArgs> WritingByte;
Signal<AddressEventArgs> ReadingByte;
void ClearMemory() {
std::fill(memory.begin(), memory.end(), 0);
}
void ClearLocking() {
std::fill(locked.begin(), locked.end(), false);
}
uint8_t GetByte(uint16_t offset) const {
auto content = memory[offset];
ReadingByte.fire(AddressEventArgs(offset, content));
return content;
}
void SetByte(uint16_t offset, uint8_t value) {
AddressEventArgs e(offset, value);
if (locked[offset]) {
InvalidWriteAttempt.fire(e);
} else {
memory[offset] = value;
WritingByte.fire(e);
}
}
void LoadRom(std::string path, uint16_t offset) {
auto length = LoadMemory(path, offset);
LockMemory(offset, length);
}
void LoadRam(std::string path, uint16_t offset) {
LoadMemory(path, offset);
}
void LockMemory(uint16_t offset, uint16_t length) {
for (auto i = 0; i < length; ++i)
locked[offset + i] = true;
}
uint16_t LoadMemory(std::string path, uint16_t offset) {
std::ifstream file(path, std::ios::binary | std::ios::ate);
auto size = (int)file.tellg();
file.seekg(0, std::ios::beg);
std::vector<char> buffer(size);
file.read(&buffer[0], size);
file.close();
std::copy(buffer.begin(), buffer.end(), memory.begin() + offset);
return (uint16_t)size;
}
};

View File

@ -1,7 +1,9 @@
#pragma once
enum ProcessorType {
Cpu6502,
Cpu65SC02,
Cpu65C02
};
namespace EightBit {
enum ProcessorType {
Cpu6502,
Cpu65SC02,
Cpu65C02
};
}

View File

@ -2,14 +2,15 @@
#include <string>
class ProfileEventArgs
{
private:
std::string m_output;
namespace EightBit {
class ProfileEventArgs {
private:
std::string m_output;
public:
ProfileEventArgs(std::string output)
: m_output(output) {}
public:
ProfileEventArgs(std::string output)
: m_output(output) {}
const std::string& getOutput() const { return m_output; }
};
const std::string& getOutput() const { return m_output; }
};
}

View File

@ -3,16 +3,18 @@
#include <string>
#include <cstdint>
class ProfileLineEventArgs
{
private:
std::string m_source;
uint64_t m_cycles;
namespace EightBit {
class ProfileLineEventArgs
{
private:
std::string m_source;
uint64_t m_cycles;
public:
ProfileLineEventArgs(std::string source, uint64_t cycles)
: m_source(source), m_cycles(cycles) {}
public:
ProfileLineEventArgs(std::string source, uint64_t cycles)
: m_source(source), m_cycles(cycles) {}
const std::string& getSource() const { return m_source; }
uint64_t getCycles() const { return m_cycles; }
};
const std::string& getSource() const { return m_source; }
uint64_t getCycles() const { return m_cycles; }
};
}

View File

@ -3,19 +3,19 @@
#include <string>
#include <cstdint>
class ProfileScopeEventArgs
{
private:
std::string m_scope;
uint64_t m_cycles;
uint64_t m_count;
namespace EightBit {
class ProfileScopeEventArgs {
private:
std::string m_scope;
uint64_t m_cycles;
uint64_t m_count;
public:
ProfileScopeEventArgs(std::string scope, uint64_t cycles, uint64_t count)
: m_scope(scope), m_cycles(cycles), m_count(count) {}
const std::string& getScope() const { return m_scope; }
uint64_t getCycles() const { return m_cycles; }
uint64_t getCount() const { return m_count; }
};
public:
ProfileScopeEventArgs(std::string scope, uint64_t cycles, uint64_t count)
: m_scope(scope), m_cycles(cycles), m_count(count) {}
const std::string& getScope() const { return m_scope; }
uint64_t getCycles() const { return m_cycles; }
uint64_t getCount() const { return m_count; }
};
}

View File

@ -5,58 +5,55 @@
#include <cstdint>
#include <functional>
#include <system6502.h>
#include <EventArgs.h>
#include <Signal.h>
#include "EventArgs.h"
#include "Signal.h"
#include "Disassembly.h"
#include "Symbols.h"
#include "AddressEventArgs.h"
#include "ProfileLineEventArgs.h"
#include "ProfileScopeEventArgs.h"
class Profiler
{
public:
std::array<uint64_t, 0x100> instructionCounts;
std::array<uint64_t, 0x10000> addressProfiles;
std::array<uint64_t, 0x10000> addressCounts;
#include "mos6502.h"
std::array<std::string, 0x10000> addressScopes;
std::map<std::string, uint64_t> scopeCycles;
namespace EightBit {
class Profiler {
public:
std::array<uint64_t, 0x100> instructionCounts;
std::array<uint64_t, 0x10000> addressProfiles;
std::array<uint64_t, 0x10000> addressCounts;
System6502& processor;
const Disassembly& disassembler;
const Symbols& symbols;
std::array<std::string, 0x10000> addressScopes;
std::map<std::string, uint64_t> scopeCycles;
bool countInstructions;
bool profileAddresses;
MOS6502& processor;
const Disassembly& disassembler;
const Symbols& symbols;
uint64_t priorCycleCount = 0;
Profiler(MOS6502& processor, Disassembly& disassembler, Symbols& symbols);
Profiler(System6502& processor, Disassembly& disassembler, Symbols& symbols, bool countInstructions, bool profileAddresses);
Signal<EventArgs> StartingOutput;
Signal<EventArgs> FinishedOutput;
Signal<EventArgs> StartingOutput;
Signal<EventArgs> FinishedOutput;
Signal<EventArgs> StartingLineOutput;
Signal<EventArgs> FinishedLineOutput;
Signal<EventArgs> StartingLineOutput;
Signal<EventArgs> FinishedLineOutput;
Signal<ProfileLineEventArgs> EmitLine;
Signal<ProfileLineEventArgs> EmitLine;
Signal<EventArgs> StartingScopeOutput;
Signal<EventArgs> FinishedScopeOutput;
Signal<EventArgs> StartingScopeOutput;
Signal<EventArgs> FinishedScopeOutput;
Signal<ProfileScopeEventArgs> EmitScope;
Signal<ProfileScopeEventArgs> EmitScope;
void addInstruction(uint8_t instruction);
void addAddress(uint16_t address, int cycles);
void Generate();
void Generate();
private:
void EmitProfileInformation();
private:
void EmitProfileInformation();
void Processor_ExecutingInstruction_ProfileAddresses(const AddressEventArgs& addressEvent);
void Processor_ExecutingInstruction_CountInstructions(const AddressEventArgs& addressEvent);
void Processor_ExecutedInstruction_ProfileAddresses(const AddressEventArgs& addressEvent);
void BuildAddressScopes();
};
void BuildAddressScopes();
};
}

View File

@ -3,80 +3,82 @@
#include <string>
#include <cstdint>
struct StatusFlags {
namespace EightBit {
struct StatusFlags {
bool negative;
bool overflow;
bool reserved;
bool brk;
bool decimal;
bool interrupt;
bool zero;
bool carry;
bool negative;
bool overflow;
bool reserved;
bool brk;
bool decimal;
bool interrupt;
bool zero;
bool carry;
enum StatusBits {
Negative = 0x80, // N
Overflow = 0x40, // V
Reserved = 0x20, // ignored
Break = 0x10, // B
Decimal = 0x08, // D (use BCD for arithmetic)
Interrupt = 0x04, // I (IRQ disable)
Zero = 0x02, // Z
Carry = 0x01, // C
enum StatusBits {
Negative = 0x80, // N
Overflow = 0x40, // V
Reserved = 0x20, // ignored
Break = 0x10, // B
Decimal = 0x08, // D (use BCD for arithmetic)
Interrupt = 0x04, // I (IRQ disable)
Zero = 0x02, // Z
Carry = 0x01, // C
};
StatusFlags(uint8_t value) {
negative = (value & StatusBits::Negative) != 0;
overflow = (value & StatusBits::Overflow) != 0;
reserved = (value & StatusBits::Reserved) != 0;
brk = (value & StatusBits::Break) != 0;
decimal = (value & StatusBits::Decimal) != 0;
interrupt = (value & StatusBits::Interrupt) != 0;
zero = (value & StatusBits::Zero) != 0;
carry = (value & StatusBits::Carry) != 0;
}
operator uint8_t() const {
uint8_t flags = 0;
if (negative)
flags |= StatusBits::Negative;
if (overflow)
flags |= StatusBits::Overflow;
if (reserved)
flags |= StatusBits::Reserved;
if (brk)
flags |= StatusBits::Break;
if (decimal)
flags |= StatusBits::Decimal;
if (interrupt)
flags |= StatusBits::Interrupt;
if (zero)
flags |= StatusBits::Zero;
if (carry)
flags |= StatusBits::Carry;
return flags;
}
operator std::string() const {
std::string returned;
returned += negative ? "N" : "-";
returned += overflow ? "O" : "-";
returned += reserved ? "R" : "-";
returned += brk ? "B" : "-";
returned += decimal ? "D" : "-";
returned += interrupt ? "I" : "-";
returned += zero ? "Z" : "-";
returned += carry ? "C" : "-";
return returned;
}
};
StatusFlags(uint8_t value) {
negative = (value & StatusBits::Negative) != 0;
overflow = (value & StatusBits::Overflow) != 0;
reserved = (value & StatusBits::Reserved) != 0;
brk = (value & StatusBits::Break) != 0;
decimal = (value & StatusBits::Decimal) != 0;
interrupt = (value & StatusBits::Interrupt) != 0;
zero = (value & StatusBits::Zero) != 0;
carry = (value & StatusBits::Carry) != 0;
}
operator uint8_t() const {
uint8_t flags = 0;
if (negative)
flags |= StatusBits::Negative;
if (overflow)
flags |= StatusBits::Overflow;
if (reserved)
flags |= StatusBits::Reserved;
if (brk)
flags |= StatusBits::Break;
if (decimal)
flags |= StatusBits::Decimal;
if (interrupt)
flags |= StatusBits::Interrupt;
if (zero)
flags |= StatusBits::Zero;
if (carry)
flags |= StatusBits::Carry;
return flags;
}
operator std::string() const {
std::string returned;
returned += negative ? "N" : "-";
returned += overflow ? "O" : "-";
returned += reserved ? "R" : "-";
returned += brk ? "B" : "-";
returned += decimal ? "D" : "-";
returned += interrupt ? "I" : "-";
returned += zero ? "Z" : "-";
returned += carry ? "C" : "-";
return returned;
}
};
}

View File

@ -5,32 +5,33 @@
#include <vector>
#include <string>
class Symbols
{
public:
Symbols(std::string path);
namespace EightBit {
class Symbols {
public:
Symbols(std::string path);
const std::map<uint16_t, std::string>& getLabels() const { return labels; }
const std::map<uint16_t, std::string>& getConstants() const { return constants; }
const std::map<std::string, uint16_t>& getScopes() const { return scopes; }
const std::map<std::string, uint64_t>& getAddresses() const { return addresses; }
const std::map<uint16_t, std::string>& getLabels() const { return labels; }
const std::map<uint16_t, std::string>& getConstants() const { return constants; }
const std::map<std::string, uint16_t>& getScopes() const { return scopes; }
const std::map<std::string, uint64_t>& getAddresses() const { return addresses; }
private:
void AssignScopes();
void AssignSymbols();
private:
void AssignScopes();
void AssignSymbols();
void Parse(std::string path);
void Parse(std::string path);
std::map<uint16_t, std::string> labels;
std::map<uint16_t, std::string> constants;
std::map<std::string, uint16_t> scopes;
std::map<std::string, uint64_t> addresses;
std::map<uint16_t, std::string> labels;
std::map<uint16_t, std::string> constants;
std::map<std::string, uint16_t> scopes;
std::map<std::string, uint64_t> addresses;
struct kv_pair_t {
std::map<std::string, std::string> element;
struct kv_pair_t {
std::map<std::string, std::string> element;
};
std::vector<std::string> split(const std::string& input, const std::vector<std::string>& delimiters);
std::map<std::string, std::map<std::string, kv_pair_t>> parsed;
};
std::vector<std::string> split(const std::string& input, const std::vector<std::string>& delimiters);
std::map<std::string, std::map<std::string, kv_pair_t>> parsed;
};
}

View File

@ -8,457 +8,462 @@
#include "ProcessorType.h"
#include "StatusFlags.h"
#include "AddressingMode.h"
#include "Signal.h"
class MOS6502 {
public:
typedef std::function<void()> instruction_t;
namespace EightBit {
class MOS6502 {
public:
typedef std::function<void()> instruction_t;
struct Instruction {
instruction_t vector = nullptr;
uint64_t count = 0;
AddressingMode mode = AddressingMode::Illegal;
std::string display = "";
struct Instruction {
instruction_t vector = nullptr;
uint64_t count = 0;
AddressingMode mode = AddressingMode::Illegal;
std::string display = "";
};
MOS6502(ProcessorType level);
Signal<MOS6502> ExecutingInstruction;
ProcessorType getLevel() const { return level; }
uint64_t getCycles() const { return cycles; }
bool getProceed() const { return proceed; }
void setProceed(bool value) { proceed = value; }
uint16_t getPC() const { return pc; }
uint8_t getX() const { return x; }
uint8_t getY() const { return y; }
uint8_t getA() const { return a; }
uint8_t getS() const { return s; }
const StatusFlags& getP() const { return p; }
const Instruction& getInstruction(uint8_t code) const {
return instructions[code];
}
virtual void Initialise();
virtual void Start(uint16_t address);
virtual void Run();
virtual void Step();
virtual void Reset();
virtual void TriggerIRQ();
virtual void TriggerNMI();
uint16_t GetWord(uint16_t offset) const;
virtual uint8_t GetByte(uint16_t offset) const = 0;
virtual void SetByte(uint16_t offset, uint8_t value) = 0;
protected:
virtual void Interrupt(uint16_t vector);
virtual void Execute(uint8_t cell);
void ___();
void ResetRegisters();
private:
static Instruction INS(instruction_t method, uint64_t cycles, AddressingMode addressing, std::string display);
static uint8_t LowNybble(uint8_t value);
static uint8_t HighNybble(uint8_t value);
static uint8_t PromoteNybble(uint8_t value);
static uint8_t DemoteNybble(uint8_t value);
static uint8_t LowByte(uint16_t value);
static uint8_t HighByte(uint16_t value);
static uint16_t MakeWord(uint8_t low, uint8_t high);
void Install6502Instructions();
void Install65sc02Instructions();
void Install65c02Instructions();
void InstallInstructionSet(std::array<Instruction, 0x100> basis);
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay);
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay, bool includeIllegal);
bool UpdateZeroFlag(uint8_t datum);
bool UpdateNegativeFlag(int8_t datum);
void UpdateZeroNegativeFlags(uint8_t datum);
void PushByte(uint8_t value);
uint8_t PopByte();
void PushWord(uint16_t value);
uint16_t PopWord();
uint8_t FetchByte();
uint16_t FetchWord();
uint16_t Address_ZeroPage();
uint16_t Address_ZeroPageX();
uint16_t Address_ZeroPageY();
uint16_t Address_IndexedIndirectX();
uint16_t Address_IndexedIndirectY_Read();
uint16_t Address_IndexedIndirectY_Write();
uint16_t Address_Absolute();
uint16_t Address_AbsoluteXIndirect();
uint16_t Address_AbsoluteX_Read();
uint16_t Address_AbsoluteX_Write();
uint16_t Address_AbsoluteY_Read();
uint16_t Address_AbsoluteY_Write();
uint16_t Address_ZeroPageIndirect();
uint8_t ReadByte_Immediate();
int8_t ReadByte_ImmediateDisplacement();
uint8_t ReadByte_ZeroPage();
uint8_t ReadByte_ZeroPageX();
uint8_t ReadByte_ZeroPageY();
uint8_t ReadByte_Absolute();
uint8_t ReadByte_AbsoluteX();
uint8_t ReadByte_AbsoluteY();
uint8_t ReadByte_IndexedIndirectX();
uint8_t ReadByte_IndirectIndexedY();
uint8_t ReadByte_ZeroPageIndirect();
void WriteByte_ZeroPage(uint8_t value);
void WriteByte_Absolute(uint8_t value);
void WriteByte_AbsoluteX(uint8_t value);
void WriteByte_AbsoluteY(uint8_t value);
void WriteByte_ZeroPageX(uint8_t value);
void WriteByte_ZeroPageY(uint8_t value);
void WriteByte_IndirectIndexedY(uint8_t value);
void WriteByte_IndexedIndirectX(uint8_t value);
void WriteByte_ZeroPageIndirect(uint8_t value);
void DEC(uint16_t offset);
uint8_t ROR(uint8_t data);
void ROR(uint16_t offset);
uint8_t LSR(uint8_t data);
void LSR(uint16_t offset);
void BIT_immediate(uint8_t data);
void BIT(uint8_t data);
void TSB(uint16_t address);
void TRB(uint16_t address);
void INC(uint16_t offset);
void ROL(uint16_t offset);
uint8_t ROL(uint8_t data);
void ASL(uint16_t offset);
uint8_t ASL(uint8_t data);
void ORA(uint8_t data);
void AND(uint8_t data);
void SBC(uint8_t data);
void SBC_b(uint8_t data);
void SBC_d(uint8_t data);
void EOR(uint8_t data);
void CPX(uint8_t data);
void CPY(uint8_t data);
void CMP(uint8_t data);
void CMP(uint8_t first, uint8_t second);
void LDA(uint8_t data);
void LDY(uint8_t data);
void LDX(uint8_t data);
void ADC(uint8_t data);
void ADC_b(uint8_t data);
void ADC_d(uint8_t data);
void RMB(uint16_t address, uint8_t flag);
void SMB(uint16_t address, uint8_t flag);
void Branch(int8_t displacement);
void Branch();
void Branch(bool flag);
void BitBranch_Clear(uint8_t check);
void BitBranch_Set(uint8_t check);
void NOP_imp();
void NOP2_imp();
void NOP3_imp();
void ORA_xind();
void ORA_zp();
void ORA_imm();
void ORA_abs();
void ORA_absx();
void ORA_absy();
void ORA_zpx();
void ORA_indy();
void ORA_zpind();
void AND_zpx();
void AND_indy();
void AND_zp();
void AND_absx();
void AND_absy();
void AND_imm();
void AND_xind();
void AND_abs();
void AND_zpind();
void EOR_absx();
void EOR_absy();
void EOR_zpx();
void EOR_indy();
void EOR_abs();
void EOR_imm();
void EOR_zp();
void EOR_xind();
void EOR_zpind();
void LDA_absx();
void LDA_absy();
void LDA_zpx();
void LDA_indy();
void LDA_abs();
void LDA_imm();
void LDA_zp();
void LDA_xind();
void LDA_zpind();
void LDX_imm();
void LDX_zp();
void LDX_abs();
void LDX_zpy();
void LDX_absy();
void LDY_imm();
void LDY_zp();
void LDY_abs();
void LDY_zpx();
void LDY_absx();
void CMP_absx();
void CMP_absy();
void CMP_zpx();
void CMP_indy();
void CMP_abs();
void CMP_imm();
void CMP_zp();
void CMP_xind();
void CMP_zpind();
void CPX_abs();
void CPX_zp();
void CPX_imm();
void CPY_imm();
void CPY_zp();
void CPY_abs();
void ADC_zp();
void ADC_xind();
void ADC_imm();
void ADC_abs();
void ADC_zpx();
void ADC_indy();
void ADC_absx();
void ADC_absy();
void ADC_zpind();
void SBC_xind();
void SBC_zp();
void SBC_imm();
void SBC_abs();
void SBC_zpx();
void SBC_indy();
void SBC_absx();
void SBC_absy();
void SBC_zpind();
void BIT_imm();
void BIT_zp();
void BIT_zpx();
void BIT_abs();
void BIT_absx();
void DEC_a();
void DEC_absx();
void DEC_zpx();
void DEC_abs();
void DEC_zp();
void DEX_imp();
void DEY_imp();
void INC_a();
void INC_zp();
void INC_absx();
void INC_zpx();
void INC_abs();
void INX_imp();
void INY_imp();
void STX_zpy();
void STX_abs();
void STX_zp();
void STY_zpx();
void STY_abs();
void STY_zp();
void STA_absx();
void STA_absy();
void STA_zpx();
void STA_indy();
void STA_abs();
void STA_zp();
void STA_xind();
void STA_zpind();
void STZ_zp();
void STZ_zpx();
void STZ_abs();
void STZ_absx();
void TSX_imp();
void TAX_imp();
void TAY_imp();
void TXS_imp();
void TYA_imp();
void TXA_imp();
void PHP_imp();
void PLP_imp();
void PLA_imp();
void PHA_imp();
void PHX_imp();
void PHY_imp();
void PLX_imp();
void PLY_imp();
void ASL_a();
void ASL_zp();
void ASL_abs();
void ASL_absx();
void ASL_zpx();
void LSR_absx();
void LSR_zpx();
void LSR_abs();
void LSR_a();
void LSR_zp();
void ROL_absx();
void ROL_zpx();
void ROL_abs();
void ROL_a();
void ROL_zp();
void ROR_absx();
void ROR_zpx();
void ROR_abs();
void ROR_a();
void ROR_zp();
void TSB_zp();
void TSB_abs();
void TRB_zp();
void TRB_abs();
void RMB0_zp();
void RMB1_zp();
void RMB2_zp();
void RMB3_zp();
void RMB4_zp();
void RMB5_zp();
void RMB6_zp();
void RMB7_zp();
void SMB0_zp();
void SMB1_zp();
void SMB2_zp();
void SMB3_zp();
void SMB4_zp();
void SMB5_zp();
void SMB6_zp();
void SMB7_zp();
void JSR_abs();
void RTI_imp();
void RTS_imp();
void JMP_abs();
void JMP_ind();
void JMP_absxind();
void BRK_imp();
void WAI_imp();
void STP_imp();
void SED_imp();
void CLD_imp();
void CLV_imp();
void SEI_imp();
void CLI_imp();
void CLC_imp();
void SEC_imp();
void BMI_rel();
void BPL_rel();
void BVC_rel();
void BVS_rel();
void BCC_rel();
void BCS_rel();
void BNE_rel();
void BEQ_rel();
void BRA_rel();
void BBR0_zprel();
void BBR1_zprel();
void BBR2_zprel();
void BBR3_zprel();
void BBR4_zprel();
void BBR5_zprel();
void BBR6_zprel();
void BBR7_zprel();
void BBS0_zprel();
void BBS1_zprel();
void BBS2_zprel();
void BBS3_zprel();
void BBS4_zprel();
void BBS5_zprel();
void BBS6_zprel();
void BBS7_zprel();
const uint16_t PageOne = 0x100;
const uint16_t IRQvector = 0xfffe;
const uint16_t RSTvector = 0xfffc;
const uint16_t NMIvector = 0xfffa;
uint16_t pc; // program counter
uint8_t x; // index register X
uint8_t y; // index register Y
uint8_t a; // accumulator
uint8_t s; // stack pointer
StatusFlags p = 0; // processor status
uint64_t cycles;
bool proceed = true;
std::array<Instruction, 0x100> instructions;
ProcessorType level;
std::array<Instruction, 0x100> overlay6502;
std::array<Instruction, 0x100> overlay65sc02;
std::array<Instruction, 0x100> overlay65c02;
};
MOS6502(ProcessorType level);
ProcessorType getLevel() const { return level; }
uint64_t getCycles() const { return cycles; }
bool getProceed() const { return proceed; }
void setProceed(bool value) { proceed = value; }
uint16_t getPC() const { return pc; }
uint8_t getX() const { return x; }
uint8_t getY() const { return y; }
uint8_t getA() const { return a; }
uint8_t getS() const { return s; }
const StatusFlags& getP() const { return p; }
const Instruction& getInstruction(uint8_t code) const {
return instructions[code];
}
virtual void Initialise();
virtual void Start(uint16_t address);
virtual void Run();
virtual void Step();
virtual void Reset();
virtual void TriggerIRQ();
virtual void TriggerNMI();
uint16_t GetWord(uint16_t offset) const;
virtual uint8_t GetByte(uint16_t offset) const = 0;
virtual void SetByte(uint16_t offset, uint8_t value) = 0;
protected:
virtual void Interrupt(uint16_t vector);
virtual void Execute(uint8_t cell);
void ___();
void ResetRegisters();
private:
static Instruction INS(instruction_t method, uint64_t cycles, AddressingMode addressing, std::string display);
static uint8_t LowNybble(uint8_t value);
static uint8_t HighNybble(uint8_t value);
static uint8_t PromoteNybble(uint8_t value);
static uint8_t DemoteNybble(uint8_t value);
static uint8_t LowByte(uint16_t value);
static uint8_t HighByte(uint16_t value);
static uint16_t MakeWord(uint8_t low, uint8_t high);
void Install6502Instructions();
void Install65sc02Instructions();
void Install65c02Instructions();
void InstallInstructionSet(std::array<Instruction, 0x100> basis);
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay);
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay, bool includeIllegal);
bool UpdateZeroFlag(uint8_t datum);
bool UpdateNegativeFlag(int8_t datum);
void UpdateZeroNegativeFlags(uint8_t datum);
void PushByte(uint8_t value);
uint8_t PopByte();
void PushWord(uint16_t value);
uint16_t PopWord();
uint8_t FetchByte();
uint16_t FetchWord();
uint16_t Address_ZeroPage();
uint16_t Address_ZeroPageX();
uint16_t Address_ZeroPageY();
uint16_t Address_IndexedIndirectX();
uint16_t Address_IndexedIndirectY_Read();
uint16_t Address_IndexedIndirectY_Write();
uint16_t Address_Absolute();
uint16_t Address_AbsoluteXIndirect();
uint16_t Address_AbsoluteX_Read();
uint16_t Address_AbsoluteX_Write();
uint16_t Address_AbsoluteY_Read();
uint16_t Address_AbsoluteY_Write();
uint16_t Address_ZeroPageIndirect();
uint8_t ReadByte_Immediate();
int8_t ReadByte_ImmediateDisplacement();
uint8_t ReadByte_ZeroPage();
uint8_t ReadByte_ZeroPageX();
uint8_t ReadByte_ZeroPageY();
uint8_t ReadByte_Absolute();
uint8_t ReadByte_AbsoluteX();
uint8_t ReadByte_AbsoluteY();
uint8_t ReadByte_IndexedIndirectX();
uint8_t ReadByte_IndirectIndexedY();
uint8_t ReadByte_ZeroPageIndirect();
void WriteByte_ZeroPage(uint8_t value);
void WriteByte_Absolute(uint8_t value);
void WriteByte_AbsoluteX(uint8_t value);
void WriteByte_AbsoluteY(uint8_t value);
void WriteByte_ZeroPageX(uint8_t value);
void WriteByte_ZeroPageY(uint8_t value);
void WriteByte_IndirectIndexedY(uint8_t value);
void WriteByte_IndexedIndirectX(uint8_t value);
void WriteByte_ZeroPageIndirect(uint8_t value);
void DEC(uint16_t offset);
uint8_t ROR(uint8_t data);
void ROR(uint16_t offset);
uint8_t LSR(uint8_t data);
void LSR(uint16_t offset);
void BIT_immediate(uint8_t data);
void BIT(uint8_t data);
void TSB(uint16_t address);
void TRB(uint16_t address);
void INC(uint16_t offset);
void ROL(uint16_t offset);
uint8_t ROL(uint8_t data);
void ASL(uint16_t offset);
uint8_t ASL(uint8_t data);
void ORA(uint8_t data);
void AND(uint8_t data);
void SBC(uint8_t data);
void SBC_b(uint8_t data);
void SBC_d(uint8_t data);
void EOR(uint8_t data);
void CPX(uint8_t data);
void CPY(uint8_t data);
void CMP(uint8_t data);
void CMP(uint8_t first, uint8_t second);
void LDA(uint8_t data);
void LDY(uint8_t data);
void LDX(uint8_t data);
void ADC(uint8_t data);
void ADC_b(uint8_t data);
void ADC_d(uint8_t data);
void RMB(uint16_t address, uint8_t flag);
void SMB(uint16_t address, uint8_t flag);
void Branch(int8_t displacement);
void Branch();
void Branch(bool flag);
void BitBranch_Clear(uint8_t check);
void BitBranch_Set(uint8_t check);
void NOP_imp();
void NOP2_imp();
void NOP3_imp();
void ORA_xind();
void ORA_zp();
void ORA_imm();
void ORA_abs();
void ORA_absx();
void ORA_absy();
void ORA_zpx();
void ORA_indy();
void ORA_zpind();
void AND_zpx();
void AND_indy();
void AND_zp();
void AND_absx();
void AND_absy();
void AND_imm();
void AND_xind();
void AND_abs();
void AND_zpind();
void EOR_absx();
void EOR_absy();
void EOR_zpx();
void EOR_indy();
void EOR_abs();
void EOR_imm();
void EOR_zp();
void EOR_xind();
void EOR_zpind();
void LDA_absx();
void LDA_absy();
void LDA_zpx();
void LDA_indy();
void LDA_abs();
void LDA_imm();
void LDA_zp();
void LDA_xind();
void LDA_zpind();
void LDX_imm();
void LDX_zp();
void LDX_abs();
void LDX_zpy();
void LDX_absy();
void LDY_imm();
void LDY_zp();
void LDY_abs();
void LDY_zpx();
void LDY_absx();
void CMP_absx();
void CMP_absy();
void CMP_zpx();
void CMP_indy();
void CMP_abs();
void CMP_imm();
void CMP_zp();
void CMP_xind();
void CMP_zpind();
void CPX_abs();
void CPX_zp();
void CPX_imm();
void CPY_imm();
void CPY_zp();
void CPY_abs();
void ADC_zp();
void ADC_xind();
void ADC_imm();
void ADC_abs();
void ADC_zpx();
void ADC_indy();
void ADC_absx();
void ADC_absy();
void ADC_zpind();
void SBC_xind();
void SBC_zp();
void SBC_imm();
void SBC_abs();
void SBC_zpx();
void SBC_indy();
void SBC_absx();
void SBC_absy();
void SBC_zpind();
void BIT_imm();
void BIT_zp();
void BIT_zpx();
void BIT_abs();
void BIT_absx();
void DEC_a();
void DEC_absx();
void DEC_zpx();
void DEC_abs();
void DEC_zp();
void DEX_imp();
void DEY_imp();
void INC_a();
void INC_zp();
void INC_absx();
void INC_zpx();
void INC_abs();
void INX_imp();
void INY_imp();
void STX_zpy();
void STX_abs();
void STX_zp();
void STY_zpx();
void STY_abs();
void STY_zp();
void STA_absx();
void STA_absy();
void STA_zpx();
void STA_indy();
void STA_abs();
void STA_zp();
void STA_xind();
void STA_zpind();
void STZ_zp();
void STZ_zpx();
void STZ_abs();
void STZ_absx();
void TSX_imp();
void TAX_imp();
void TAY_imp();
void TXS_imp();
void TYA_imp();
void TXA_imp();
void PHP_imp();
void PLP_imp();
void PLA_imp();
void PHA_imp();
void PHX_imp();
void PHY_imp();
void PLX_imp();
void PLY_imp();
void ASL_a();
void ASL_zp();
void ASL_abs();
void ASL_absx();
void ASL_zpx();
void LSR_absx();
void LSR_zpx();
void LSR_abs();
void LSR_a();
void LSR_zp();
void ROL_absx();
void ROL_zpx();
void ROL_abs();
void ROL_a();
void ROL_zp();
void ROR_absx();
void ROR_zpx();
void ROR_abs();
void ROR_a();
void ROR_zp();
void TSB_zp();
void TSB_abs();
void TRB_zp();
void TRB_abs();
void RMB0_zp();
void RMB1_zp();
void RMB2_zp();
void RMB3_zp();
void RMB4_zp();
void RMB5_zp();
void RMB6_zp();
void RMB7_zp();
void SMB0_zp();
void SMB1_zp();
void SMB2_zp();
void SMB3_zp();
void SMB4_zp();
void SMB5_zp();
void SMB6_zp();
void SMB7_zp();
void JSR_abs();
void RTI_imp();
void RTS_imp();
void JMP_abs();
void JMP_ind();
void JMP_absxind();
void BRK_imp();
void WAI_imp();
void STP_imp();
void SED_imp();
void CLD_imp();
void CLV_imp();
void SEI_imp();
void CLI_imp();
void CLC_imp();
void SEC_imp();
void BMI_rel();
void BPL_rel();
void BVC_rel();
void BVS_rel();
void BCC_rel();
void BCS_rel();
void BNE_rel();
void BEQ_rel();
void BRA_rel();
void BBR0_zprel();
void BBR1_zprel();
void BBR2_zprel();
void BBR3_zprel();
void BBR4_zprel();
void BBR5_zprel();
void BBR6_zprel();
void BBR7_zprel();
void BBS0_zprel();
void BBS1_zprel();
void BBS2_zprel();
void BBS3_zprel();
void BBS4_zprel();
void BBS5_zprel();
void BBS6_zprel();
void BBS7_zprel();
const uint16_t PageOne = 0x100;
const uint16_t IRQvector = 0xfffe;
const uint16_t RSTvector = 0xfffc;
const uint16_t NMIvector = 0xfffa;
uint16_t pc; // program counter
uint8_t x; // index register X
uint8_t y; // index register Y
uint8_t a; // accumulator
uint8_t s; // stack pointer
StatusFlags p = 0; // processor status
uint64_t cycles;
bool proceed = true;
std::array<Instruction, 0x100> instructions;
ProcessorType level;
std::array<Instruction, 0x100> overlay6502;
std::array<Instruction, 0x100> overlay65sc02;
std::array<Instruction, 0x100> overlay65c02;
};
}

View File

@ -1,69 +0,0 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <ctime>
#include <chrono>
#include <functional>
#include "mos6502.h"
#include "EventArgs.h"
#include "AddressEventArgs.h"
#include "Signal.h"
#include "Memory.h"
class System6502 : public MOS6502
{
public:
const double Mega = 1000000;
const double Milli = 0.001;
const unsigned MemorySize = 0x10000;
uint64_t getHeldCycles() const { return heldCycles; }
public:
System6502(ProcessorType level, double speed, clock_t pollInterval);
Memory& getMemory() {
return memory;
}
virtual void Initialise();
virtual void Run();
Signal<EventArgs> Starting;
Signal<EventArgs> Finished;
Signal<EventArgs> Polling;
Signal<AddressEventArgs> ExecutingInstruction;
Signal<AddressEventArgs> ExecutedInstruction;
virtual uint8_t GetByte(uint16_t offset) const;
virtual void SetByte(uint16_t offset, uint8_t value);
protected:
virtual void Execute(uint8_t cell);
private:
void CheckPoll();
void System6502_Starting();
void System6502_Finished();
void Throttle();
double speed; // Speed in MHz, e.g. 2.0 == 2Mhz, 1.79 = 1.79Mhz
double cyclesPerSecond;
double cyclesPerMillisecond;
uint64_t cyclesPerInterval;
uint64_t intervalCycles;
uint64_t heldCycles = 0;
bool running;
Memory memory;
std::chrono::high_resolution_clock::time_point startTime;
};

View File

@ -1,23 +0,0 @@
namespace Processor
{
public enum AddressingMode
{
Illegal,
Implied,
Accumulator,
Immediate,
Relative,
XIndexed,
IndexedY,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteY,
AbsoluteXIndirect,
Indirect,
ZeroPageIndirect,
ZeroPageRelative
}
}

View File

@ -7,10 +7,9 @@
using namespace std::placeholders;
Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
EightBit::Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
: processor(targetProcessor),
symbols(targetSymbols)
{
symbols(targetSymbols) {
dumpers = {
{ AddressingMode::Illegal, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1) } },
{ AddressingMode::Implied, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1) } },
@ -32,23 +31,23 @@ Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
};
}
std::string Disassembly::Dump_ByteValue(uint8_t value) const {
std::string EightBit::Disassembly::Dump_ByteValue(uint8_t value) const {
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;
return output.str();
}
std::string Disassembly::Dump_WordValue(uint16_t value) const {
std::string EightBit::Disassembly::Dump_WordValue(uint16_t value) const {
std::ostringstream output;
output << std::hex << std::setw(4) << std::setfill('0') << (int)value;
return output.str();
}
std::string Disassembly::DumpBytes(AddressingMode mode, uint16_t current) const {
std::string EightBit::Disassembly::DumpBytes(AddressingMode mode, uint16_t current) const {
return getDumper(mode).byteDumper(current);
}
std::string Disassembly::Disassemble(uint16_t current) const {
std::string EightBit::Disassembly::Disassemble(uint16_t current) const {
std::ostringstream output;
@ -68,37 +67,37 @@ std::string Disassembly::Disassemble(uint16_t current) const {
return output.str();
}
std::string Disassembly::DumpOperand(AddressingMode mode, uint16_t current) const {
std::string EightBit::Disassembly::DumpOperand(AddressingMode mode, uint16_t current) const {
return getDumper(mode).disassemblyDumper(current);
}
////
uint8_t Disassembly::GetByte(uint16_t address) const {
uint8_t EightBit::Disassembly::GetByte(uint16_t address) const {
return processor.GetByte(address);
}
uint16_t Disassembly::GetWord(uint16_t address) const {
uint16_t EightBit::Disassembly::GetWord(uint16_t address) const {
return processor.GetWord(address);
}
////
std::string Disassembly::Dump_Nothing(uint16_t) const {
std::string EightBit::Disassembly::Dump_Nothing(uint16_t) const {
return "";
}
std::string Disassembly::Dump_Byte(uint16_t address) const {
std::string EightBit::Disassembly::Dump_Byte(uint16_t address) const {
return Dump_ByteValue(GetByte(address));
}
std::string Disassembly::Dump_DByte(uint16_t address) const {
std::string EightBit::Disassembly::Dump_DByte(uint16_t address) const {
return Dump_Byte(address) + Dump_Byte(address + 1);
}
////
std::string Disassembly::ConvertAddress(uint16_t address) const {
std::string EightBit::Disassembly::ConvertAddress(uint16_t address) const {
auto label = symbols.getLabels().find(address);
if (label != symbols.getLabels().end())
return label->second;
@ -107,7 +106,7 @@ std::string Disassembly::ConvertAddress(uint16_t address) const {
return output.str();
}
std::string Disassembly::ConvertAddress(uint8_t address) const {
std::string EightBit::Disassembly::ConvertAddress(uint8_t address) const {
auto label = symbols.getLabels().find(address);
if (label != symbols.getLabels().end())
return label->second;
@ -116,14 +115,14 @@ std::string Disassembly::ConvertAddress(uint8_t address) const {
return output.str();
}
std::string Disassembly::ConvertConstant(uint16_t constant) const {
std::string EightBit::Disassembly::ConvertConstant(uint16_t constant) const {
auto label = symbols.getConstants().find(constant);
if (label != symbols.getConstants().end())
return label->second;
return Dump_DByte(constant);
}
std::string Disassembly::ConvertConstant(uint8_t constant) const {
std::string EightBit::Disassembly::ConvertConstant(uint8_t constant) const {
auto label = symbols.getConstants().find(constant);
if (label != symbols.getConstants().end())
return label->second;
@ -132,96 +131,96 @@ std::string Disassembly::ConvertConstant(uint8_t constant) const {
////
std::string Disassembly::Dump_A(uint16_t) const {
std::string EightBit::Disassembly::Dump_A(uint16_t) const {
return "A";
}
std::string Disassembly::Dump_imm(uint16_t current) const {
std::string EightBit::Disassembly::Dump_imm(uint16_t current) const {
std::ostringstream output;
auto immediate = GetByte(current);
output << "#" << ConvertConstant(immediate);
return output.str();
}
std::string Disassembly::Dump_abs(uint16_t current) const {
std::string EightBit::Disassembly::Dump_abs(uint16_t current) const {
auto address = GetWord(current);
return ConvertAddress(address);
}
std::string Disassembly::Dump_zp(uint16_t current) const {
std::string EightBit::Disassembly::Dump_zp(uint16_t current) const {
auto zp = GetByte(current);
return ConvertAddress(zp);
}
std::string Disassembly::Dump_zpx(uint16_t current) const {
std::string EightBit::Disassembly::Dump_zpx(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << ConvertAddress(zp) << ",X";
return output.str();
}
std::string Disassembly::Dump_zpy(uint16_t current) const {
std::string EightBit::Disassembly::Dump_zpy(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << ConvertAddress(zp) << ",Y";
return output.str();
}
std::string Disassembly::Dump_absx(uint16_t current) const {
std::string EightBit::Disassembly::Dump_absx(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << ConvertAddress(address) << ",X";
return output.str();
}
std::string Disassembly::Dump_absy(uint16_t current) const {
std::string EightBit::Disassembly::Dump_absy(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << ConvertAddress(address) << ",Y";
return output.str();
}
std::string Disassembly::Dump_absxind(uint16_t current) const {
std::string EightBit::Disassembly::Dump_absxind(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << "(" << ConvertAddress(address) << ",X)";
return output.str();
}
std::string Disassembly::Dump_xind(uint16_t current) const {
std::string EightBit::Disassembly::Dump_xind(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << ",X)";
return output.str();
}
std::string Disassembly::Dump_indy(uint16_t current) const {
std::string EightBit::Disassembly::Dump_indy(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << "),Y";
return output.str();
}
std::string Disassembly::Dump_ind(uint16_t current) const {
std::string EightBit::Disassembly::Dump_ind(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << "(" << ConvertAddress(address) << ")";
return output.str();
}
std::string Disassembly::Dump_zpind(uint16_t current) const {
std::string EightBit::Disassembly::Dump_zpind(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << ")";
return output.str();
}
std::string Disassembly::Dump_rel(uint16_t current) const {
std::string EightBit::Disassembly::Dump_rel(uint16_t current) const {
uint16_t relative = 1 + current + (int8_t)GetByte(current);
return ConvertAddress(relative);
}
std::string Disassembly::Dump_zprel(uint16_t current) const {
std::string EightBit::Disassembly::Dump_zprel(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
int8_t displacement = GetByte(current + 1);

167
M6502/src/M6502.vcxproj Normal file
View File

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{D8726A1B-BBFE-47EF-9860-26B90140BA66}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>M6502</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\inc\AddressingMode.h" />
<ClInclude Include="..\inc\AddressingModeDumper.h" />
<ClInclude Include="..\inc\Disassembly.h" />
<ClInclude Include="..\inc\DisassemblyEventArgs.h" />
<ClInclude Include="..\inc\mos6502.h" />
<ClInclude Include="..\inc\ProcessorType.h" />
<ClInclude Include="..\inc\ProfileEventArgs.h" />
<ClInclude Include="..\inc\ProfileLineEventArgs.h" />
<ClInclude Include="..\inc\Profiler.h" />
<ClInclude Include="..\inc\ProfileScopeEventArgs.h" />
<ClInclude Include="..\inc\StatusFlags.h" />
<ClInclude Include="..\inc\Symbols.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Disassembly.cpp" />
<ClCompile Include="mos6502.cpp" />
<ClCompile Include="Profiler.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Symbols.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\AddressingMode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\AddressingModeDumper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\Disassembly.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\DisassemblyEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\mos6502.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\ProcessorType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\ProfileEventArgs.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>
<ClInclude Include="..\inc\ProfileScopeEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\StatusFlags.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\Symbols.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Disassembly.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mos6502.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Profiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Symbols.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,9 +0,0 @@
namespace Processor
{
public enum ProcessorType
{
Cpu6502,
Cpu65SC02,
Cpu65C02
}
}

View File

@ -1,34 +1,25 @@
#include "stdafx.h"
#include "Profiler.h"
Profiler::Profiler(System6502& targetProcessor, Disassembly& disassemblerTarget, Symbols& symbolsTarget, bool instructions, bool addresses)
EightBit::Profiler::Profiler(MOS6502& targetProcessor, Disassembly& disassemblerTarget, Symbols& symbolsTarget)
: processor(targetProcessor),
disassembler(disassemblerTarget),
symbols(symbolsTarget),
countInstructions(instructions),
profileAddresses(addresses)
{
symbols(symbolsTarget) {
instructionCounts.fill(0);
addressProfiles.fill(0);
addressCounts.fill(0);
if (profileAddresses)
processor.ExecutingInstruction.connect(std::bind(&Profiler::Processor_ExecutingInstruction_ProfileAddresses, this, std::placeholders::_1));
if (countInstructions)
processor.ExecutingInstruction.connect(std::bind(&Profiler::Processor_ExecutingInstruction_CountInstructions, this, std::placeholders::_1));
if (profileAddresses)
processor.ExecutedInstruction.connect(std::bind(&Profiler::Processor_ExecutedInstruction_ProfileAddresses, this, std::placeholders::_1));
BuildAddressScopes();
}
void Profiler::Generate() {
void EightBit::Profiler::Generate() {
StartingOutput.fire(EventArgs());
EmitProfileInformation();
StartingOutput.fire(EventArgs());
}
void Profiler::EmitProfileInformation() {
void EightBit::Profiler::EmitProfileInformation() {
{
StartingLineOutput.fire(EventArgs());
@ -58,22 +49,16 @@ void Profiler::EmitProfileInformation() {
}
}
void Profiler::Processor_ExecutingInstruction_ProfileAddresses(const AddressEventArgs& addressEvent) {
assert(profileAddresses);
priorCycleCount = processor.getCycles();
addressCounts[addressEvent.getAddress()]++;
void EightBit::Profiler::addInstruction(uint8_t instruction) {
++instructionCounts[instruction];
}
void Profiler::Processor_ExecutingInstruction_CountInstructions(const AddressEventArgs& addressEvent) {
assert(countInstructions);
++instructionCounts[addressEvent.getCell()];
}
void EightBit::Profiler::addAddress(uint16_t address, int cycles) {
void Profiler::Processor_ExecutedInstruction_ProfileAddresses(const AddressEventArgs& addressEvent) {
assert(profileAddresses);
auto cycles = processor.getCycles() - priorCycleCount;
addressProfiles[addressEvent.getAddress()] += cycles;
auto addressScope = addressScopes[addressEvent.getAddress()];
addressCounts[address]++;
addressProfiles[address] += cycles;
auto addressScope = addressScopes[address];
if (!addressScope.empty()) {
if (scopeCycles.find(addressScope) == scopeCycles.end())
scopeCycles[addressScope] = 0;
@ -81,7 +66,7 @@ void Profiler::Processor_ExecutedInstruction_ProfileAddresses(const AddressEvent
}
}
void Profiler::BuildAddressScopes() {
void EightBit::Profiler::BuildAddressScopes() {
for (auto& label : symbols.getLabels()) {
auto address = label.first;
auto key = label.second;

View File

@ -10,7 +10,7 @@
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
Symbols::Symbols(std::string path) {
EightBit::Symbols::Symbols(std::string path) {
if (!path.empty()) {
Parse(path);
AssignSymbols();
@ -18,7 +18,7 @@ Symbols::Symbols(std::string path) {
}
}
void Symbols::AssignScopes() {
void EightBit::Symbols::AssignScopes() {
auto parsedScopes = parsed["scope"];
for(auto& parsedScopeElement : parsedScopes) {
auto& parsedScope = parsedScopeElement.second.element;
@ -29,7 +29,7 @@ void Symbols::AssignScopes() {
}
}
void Symbols::AssignSymbols() {
void EightBit::Symbols::AssignSymbols() {
auto symbols = parsed["sym"];
for(auto& symbolElement : symbols) {
auto& symbol = symbolElement.second.element;
@ -47,7 +47,7 @@ void Symbols::AssignSymbols() {
}
}
void Symbols::Parse(std::string path) {
void EightBit::Symbols::Parse(std::string path) {
std::string line;
std::ifstream reader(path);
while (std::getline(reader, line)) {
@ -73,7 +73,7 @@ void Symbols::Parse(std::string path) {
}
}
std::vector<std::string> Symbols::split(const std::string& input, const std::vector<std::string>& delimiters) {
std::vector<std::string> EightBit::Symbols::split(const std::string& input, const std::vector<std::string>& delimiters) {
std::vector<std::string> tokens;
boost::algorithm::split_regex(
tokens,

File diff suppressed because it is too large Load Diff

1
M6502/src/stdafx.cpp Normal file
View File

@ -0,0 +1 @@
#include "stdafx.h"

1
M6502/src/stdafx.h Normal file
View File

@ -0,0 +1 @@
#pragma once

View File

@ -1,91 +0,0 @@
#include "stdafx.h"
#include "system6502.h"
#include <thread>
#include <functional>
System6502::System6502(ProcessorType level, double processorSpeed, clock_t pollInterval)
: MOS6502(level),
memory(MemorySize)
{
speed = processorSpeed;
cyclesPerSecond = speed * Mega; // speed is in MHz
cyclesPerMillisecond = cyclesPerSecond * Milli;
cyclesPerInterval = (uint64_t)(cyclesPerMillisecond * pollInterval);
Starting.connect(std::bind(&System6502::System6502_Starting, this));
Finished.connect(std::bind(&System6502::System6502_Finished, this));
}
void System6502::Initialise() {
__super::Initialise();
memory.ClearLocking();
memory.ClearMemory();
intervalCycles = 0;
}
void System6502::Run() {
Starting.fire(EventArgs());
__super::Run();
Finished.fire(EventArgs());
}
uint8_t System6502::GetByte(uint16_t offset) const {
return memory.GetByte(offset);
}
void System6502::SetByte(uint16_t offset, uint8_t value) {
memory.SetByte(offset, value);
}
void System6502::Execute(uint8_t cell) {
auto oldCycles = getCycles();
CheckPoll();
// XXXX Fetch byte has already incremented PC.
auto executingAddress = (uint16_t)(getPC() - 1);
AddressEventArgs e(executingAddress, cell);
ExecutingInstruction.fire(e);
__super::Execute(cell);
ExecutedInstruction.fire(e);
auto deltaCycles = getCycles() - oldCycles;
intervalCycles += deltaCycles;
}
void System6502::CheckPoll() {
if (intervalCycles >= cyclesPerInterval) {
intervalCycles -= cyclesPerInterval;
Throttle();
Polling.fire(EventArgs());
}
}
void System6502::System6502_Starting() {
startTime = std::chrono::high_resolution_clock::now();
running = true;
}
void System6502::System6502_Finished() {
running = false;
}
void System6502::Throttle() {
auto now = std::chrono::high_resolution_clock::now();
auto elapsed = now - startTime;
auto timerCurrent = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
auto cyclesAllowed = timerCurrent * cyclesPerMillisecond;
auto cyclesMismatch = getCycles() - cyclesAllowed;
if (cyclesMismatch > 0.0) {
auto delay = cyclesMismatch / cyclesPerMillisecond;
if (delay > 0) {
heldCycles += (uint64_t)cyclesMismatch;
std::this_thread::sleep_for(std::chrono::milliseconds((long long)delay));
}
}
}

18
inc/AddressEventArgs.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <cstdint>
namespace EightBit {
class AddressEventArgs {
private:
uint16_t m_address;
uint8_t m_cell;
public:
AddressEventArgs(uint16_t address, uint8_t cell)
: m_address(address), m_cell(cell) {}
uint16_t getAddress() const { return m_address; }
uint8_t getCell() const { return m_cell; }
};
}

View File

@ -4,6 +4,9 @@
#include <cstdint>
#include <string>
#include "Signal.h"
#include "AddressEventArgs.h"
#if defined(_M_X64) || defined(_M_IX86 )
# define HOST_LITTLE_ENDIAN
#else
@ -39,6 +42,10 @@ namespace EightBit {
Memory(uint16_t addressMask);
// Only fired with read/write methods
Signal<AddressEventArgs> WritingByte;
Signal<AddressEventArgs> ReadingByte;
register16_t& ADDRESS() { return m_address; }
uint8_t& DATA() { return *m_data; }
@ -65,6 +72,20 @@ namespace EightBit {
return address & m_addressMask;
}
uint8_t read(uint16_t offset) {
ADDRESS().word = offset;
const auto content = reference();
ReadingByte.fire(AddressEventArgs(offset, content));
return content;
}
void write(uint16_t offset, uint8_t value) {
AddressEventArgs e(offset, value);
WritingByte.fire(e);
ADDRESS().word = offset;
reference() = value;
}
void clear();
void loadRom(const std::string& path, uint16_t offset);
void loadRam(const std::string& path, uint16_t offset);

View File

@ -138,6 +138,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\inc\AddressEventArgs.h" />
<ClInclude Include="..\inc\EventArgs.h" />
<ClInclude Include="..\inc\IntelProcessor.h" />
<ClInclude Include="..\inc\Memory.h" />

View File

@ -32,6 +32,9 @@
<ClInclude Include="..\inc\TestHarness.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\AddressEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">