95 lines
3.1 KiB
C++
95 lines
3.1 KiB
C++
#include "stdafx.h"
|
|
#include "Profiler.h"
|
|
|
|
Profiler::Profiler(System6502& targetProcessor, Disassembly& disassemblerTarget, Symbols& symbolsTarget, bool instructions, bool addresses)
|
|
: processor(targetProcessor),
|
|
disassembler(disassemblerTarget),
|
|
symbols(symbolsTarget),
|
|
countInstructions(instructions),
|
|
profileAddresses(addresses)
|
|
{
|
|
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() {
|
|
StartingOutput.fire(EventArgs());
|
|
EmitProfileInformation();
|
|
StartingOutput.fire(EventArgs());
|
|
}
|
|
|
|
void Profiler::EmitProfileInformation() {
|
|
|
|
{
|
|
StartingLineOutput.fire(EventArgs());
|
|
// For each memory address
|
|
for (uint16_t 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);
|
|
EmitLine.fire(ProfileLineEventArgs(source, cycles));
|
|
}
|
|
}
|
|
FinishedLineOutput.fire(EventArgs());
|
|
}
|
|
|
|
{
|
|
StartingScopeOutput.fire(EventArgs());
|
|
for (auto& scopeCycle : scopeCycles) {
|
|
auto name = scopeCycle.first;
|
|
auto cycles = scopeCycle.second;
|
|
auto namedAddress = (size_t)symbols.getAddresses().find(name)->second;
|
|
auto count = addressCounts[namedAddress];
|
|
EmitScope.fire(ProfileScopeEventArgs(name, cycles, count));
|
|
}
|
|
FinishedScopeOutput.fire(EventArgs());
|
|
}
|
|
}
|
|
|
|
void Profiler::Processor_ExecutingInstruction_ProfileAddresses(const AddressEventArgs& addressEvent) {
|
|
assert(profileAddresses);
|
|
priorCycleCount = processor.getCycles();
|
|
addressCounts[addressEvent.getAddress()]++;
|
|
}
|
|
|
|
void Profiler::Processor_ExecutingInstruction_CountInstructions(const AddressEventArgs& addressEvent) {
|
|
assert(countInstructions);
|
|
++instructionCounts[addressEvent.getCell()];
|
|
}
|
|
|
|
void Profiler::Processor_ExecutedInstruction_ProfileAddresses(const AddressEventArgs& addressEvent) {
|
|
assert(profileAddresses);
|
|
auto cycles = processor.getCycles() - priorCycleCount;
|
|
addressProfiles[addressEvent.getAddress()] += cycles;
|
|
auto addressScope = addressScopes[addressEvent.getAddress()];
|
|
if (!addressScope.empty()) {
|
|
if (scopeCycles.find(addressScope) == scopeCycles.end())
|
|
scopeCycles[addressScope] = 0;
|
|
scopeCycles[addressScope] += cycles;
|
|
}
|
|
}
|
|
|
|
void Profiler::BuildAddressScopes() {
|
|
for (auto& label : symbols.getLabels()) {
|
|
auto address = label.first;
|
|
auto key = label.second;
|
|
auto scope = symbols.getScopes().find(key);
|
|
if (scope != symbols.getScopes().end()) {
|
|
for (uint16_t i = address; i < address + scope->second; ++i) {
|
|
addressScopes[i] = key;
|
|
}
|
|
}
|
|
}
|
|
} |