mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-04-21 17:37:04 +00:00
Add 6809 profiling
This commit is contained in:
parent
b1ca06447f
commit
79adce86bd
@ -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);
|
||||
};
|
||||
}
|
22
MC6809/inc/ProfileLineEventArgs.h
Normal file
22
MC6809/inc/ProfileLineEventArgs.h
Normal 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
41
MC6809/inc/Profiler.h
Normal 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();
|
||||
};
|
||||
}
|
@ -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>
|
||||
|
@ -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
41
MC6809/src/Profiler.cpp
Normal 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;
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user