mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Debugger: Added "Show jump labels" option
This commit is contained in:
parent
b887e2b5f2
commit
5414afdbb4
27 changed files with 221 additions and 90 deletions
|
@ -38,6 +38,11 @@ public:
|
|||
_cdlData[absoluteAddr] |= CdlFlags::Code | flags;
|
||||
}
|
||||
|
||||
void SetCode(int32_t absoluteAddr, uint8_t flags)
|
||||
{
|
||||
_cdlData[absoluteAddr] |= CdlFlags::Code | flags;
|
||||
}
|
||||
|
||||
template<uint8_t flags = 0>
|
||||
void SetData(int32_t absoluteAddr)
|
||||
{
|
||||
|
|
|
@ -105,6 +105,7 @@ struct DisassemblyResult
|
|||
Flags = flags;
|
||||
CpuAddress = cpuAddress;
|
||||
Address.Address = -1;
|
||||
Address.Type = {};
|
||||
CommentLine = commentLine;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ vector<DisassemblyResult> Disassembler::Disassemble(CpuType cpuType, uint16_t ba
|
|||
bool disData = _settings->CheckDebuggerFlag(DebuggerFlags::DisassembleVerifiedData);
|
||||
bool showUnident = _settings->CheckDebuggerFlag(DebuggerFlags::ShowUnidentifiedData);
|
||||
bool showData = _settings->CheckDebuggerFlag(DebuggerFlags::ShowVerifiedData);
|
||||
bool showJumpLabels = _settings->CheckDebuggerFlag(DebuggerFlags::ShowJumpLabels);
|
||||
|
||||
bool inUnknownBlock = false;
|
||||
bool inVerifiedBlock = false;
|
||||
|
@ -216,6 +217,9 @@ vector<DisassemblyResult> Disassembler::Disassemble(CpuType cpuType, uint16_t ba
|
|||
} else {
|
||||
results.push_back(DisassemblyResult(addrInfo, i));
|
||||
}
|
||||
} else if(showJumpLabels && cdl && (cdl->IsJumpTarget(addrInfo.Address) || cdl->IsSubEntryPoint(addrInfo.Address))) {
|
||||
results.push_back(DisassemblyResult(addrInfo, i, LineFlags::Label));
|
||||
results.push_back(DisassemblyResult(addrInfo, i));
|
||||
} else {
|
||||
results.push_back(DisassemblyResult(addrInfo, i));
|
||||
}
|
||||
|
@ -310,6 +314,7 @@ void Disassembler::GetLineData(DisassemblyResult& row, CpuType type, MemoryType
|
|||
case MemoryType::GbCartRam:
|
||||
case MemoryType::SnesSaveRam:
|
||||
case MemoryType::NesSaveRam:
|
||||
case MemoryType::PceSaveRam:
|
||||
data.Flags |= (uint8_t)LineFlags::SaveRam;
|
||||
break;
|
||||
}
|
||||
|
@ -329,7 +334,15 @@ void Disassembler::GetLineData(DisassemblyResult& row, CpuType type, MemoryType
|
|||
data.Flags |= LineFlags::VerifiedCode;
|
||||
memcpy(data.Comment, comment.c_str(), std::min<int>((int)comment.size() + 1, 1000));
|
||||
} else if(data.Flags & LineFlags::Label) {
|
||||
string label = _labelManager->GetLabel(row.Address) + ":";
|
||||
string label = _labelManager->GetLabel(row.Address);
|
||||
if(label.empty()) {
|
||||
//Use address as the label
|
||||
label = "$" + DebugUtilities::AddressToHex(type, row.CpuAddress);
|
||||
if(_settings->CheckDebuggerFlag(DebuggerFlags::UseLowerCaseDisassembly)) {
|
||||
std::transform(label.begin(), label.end(), label.begin(), ::tolower);
|
||||
}
|
||||
}
|
||||
label += ":";
|
||||
data.Flags |= LineFlags::VerifiedCode;
|
||||
memcpy(data.Text, label.c_str(), std::min<int>((int)label.size() + 1, 1000));
|
||||
} else {
|
||||
|
|
|
@ -248,6 +248,43 @@ bool GameboyDisUtils::IsConditionalJump(uint8_t opCode)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
CdlFlags::CdlFlags GameboyDisUtils::GetOpFlags(uint8_t opCode, uint16_t pc, uint16_t prevPc)
|
||||
{
|
||||
switch(opCode) {
|
||||
case 0xC4: //CALL NZ,a16
|
||||
case 0xC7: //RST 00H
|
||||
case 0xCD: //CALL a16
|
||||
case 0xCC: //CALL Z,a16
|
||||
case 0xCF: //RST 08H
|
||||
case 0xD4: //CALL NC,a16
|
||||
case 0xD7: //RST 10H
|
||||
case 0xDC: //CALL C,a16
|
||||
case 0xDF: //RST 18H
|
||||
case 0xE7: //RST 20H
|
||||
case 0xEF: //RST 28H
|
||||
case 0xF7: //RST 30H
|
||||
case 0xFF: //RST 38H
|
||||
return CdlFlags::SubEntryPoint;
|
||||
|
||||
case 0x18: //JR r8
|
||||
case 0xC3: //JP a16
|
||||
case 0xE9: //JP (HL)
|
||||
case 0x20: //JR NZ,r8
|
||||
case 0x28: //JR Z,r8
|
||||
case 0x30: //JR NC,r8
|
||||
case 0x38: //JR C,r8
|
||||
case 0xC2: //JP NZ,a16
|
||||
case 0xCA: //JP Z,a16
|
||||
case 0xD2: //JP NC,a16
|
||||
case 0xDA: //JP C,a16
|
||||
return pc != prevPc + GameboyDisUtils::GetOpSize(opCode) ? CdlFlags::JumpTarget : CdlFlags::None;
|
||||
|
||||
default:
|
||||
return CdlFlags::None;
|
||||
}
|
||||
}
|
||||
|
||||
string GameboyDisUtils::GetOpTemplate(uint8_t op, bool prefixed)
|
||||
{
|
||||
return prefixed ? _cbTemplate[op] : _opTemplate[op];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Debugger/DebugTypes.h"
|
||||
|
||||
class DisassemblyInfo;
|
||||
class LabelManager;
|
||||
|
@ -16,5 +17,6 @@ public:
|
|||
static bool IsReturnInstruction(uint8_t opCode);
|
||||
static bool IsUnconditionalJump(uint8_t opCode);
|
||||
static bool IsConditionalJump(uint8_t opCode);
|
||||
static CdlFlags::CdlFlags GetOpFlags(uint8_t opCode, uint16_t pc, uint16_t prevPc);
|
||||
static string GetOpTemplate(uint8_t op, bool prefixed);
|
||||
};
|
||||
|
|
|
@ -90,11 +90,7 @@ void GbDebugger::ProcessInstruction()
|
|||
|
||||
if(addressInfo.Address >= 0) {
|
||||
if(addressInfo.Type == MemoryType::GbPrgRom) {
|
||||
if(GameboyDisUtils::IsJumpToSub(_prevOpCode)) {
|
||||
_codeDataLogger->SetCode<CdlFlags::SubEntryPoint>(addressInfo.Address);
|
||||
} else {
|
||||
_codeDataLogger->SetCode(addressInfo.Address);
|
||||
}
|
||||
_codeDataLogger->SetCode(addressInfo.Address, GameboyDisUtils::GetOpFlags(_prevOpCode, pc, _prevProgramCounter));
|
||||
}
|
||||
_disassembler->BuildCache(addressInfo, 0, CpuType::Gameboy);
|
||||
}
|
||||
|
@ -263,6 +259,10 @@ void GbDebugger::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool
|
|||
AddressInfo ret = _gameboy->GetAbsoluteAddress(originalPc);
|
||||
AddressInfo dest = _gameboy->GetAbsoluteAddress(currentPc);
|
||||
|
||||
if(dest.Type == MemoryType::GbPrgRom && dest.Address >= 0) {
|
||||
_codeDataLogger->SetCode(dest.Address, CdlFlags::SubEntryPoint);
|
||||
}
|
||||
|
||||
_debugger->InternalProcessInterrupt(
|
||||
CpuType::Gameboy, *this, *_step.get(),
|
||||
src, _prevProgramCounter, dest, currentPc, ret, originalPc, forNmi
|
||||
|
|
|
@ -97,26 +97,21 @@ void NesDebugger::Reset()
|
|||
void NesDebugger::ProcessInstruction()
|
||||
{
|
||||
NesCpuState& state = _cpu->GetState();
|
||||
uint16_t addr = state.PC;
|
||||
uint8_t value = _memoryManager->DebugRead(addr);
|
||||
AddressInfo addressInfo = _mapper->GetAbsoluteAddress(addr);
|
||||
MemoryOperationInfo operation(addr, value, MemoryOperationType::ExecOpCode, MemoryType::NesMemory);
|
||||
uint16_t pc = state.PC;
|
||||
uint8_t opCode = _memoryManager->DebugRead(pc);
|
||||
AddressInfo addressInfo = _mapper->GetAbsoluteAddress(pc);
|
||||
MemoryOperationInfo operation(pc, opCode, MemoryOperationType::ExecOpCode, MemoryType::NesMemory);
|
||||
|
||||
bool needDisassemble = _traceLogger->IsEnabled() || _settings->CheckDebuggerFlag(DebuggerFlags::NesDebuggerEnabled);
|
||||
if(addressInfo.Address >= 0) {
|
||||
if(addressInfo.Type == MemoryType::NesPrgRom) {
|
||||
if(NesDisUtils::IsJumpToSub(_prevOpCode)) {
|
||||
_codeDataLogger->SetCode<CdlFlags::SubEntryPoint>(addressInfo.Address);
|
||||
} else {
|
||||
_codeDataLogger->SetCode(addressInfo.Address);
|
||||
}
|
||||
_codeDataLogger->SetCode(addressInfo.Address, NesDisUtils::GetOpFlags(_prevOpCode, pc, _prevProgramCounter));
|
||||
}
|
||||
if(needDisassemble) {
|
||||
_disassembler->BuildCache(addressInfo, 0, CpuType::Nes);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pc = state.PC;
|
||||
if(NesDisUtils::IsJumpToSub(_prevOpCode)) {
|
||||
//JSR
|
||||
uint8_t opSize = NesDisUtils::GetOpSize(_prevOpCode);
|
||||
|
@ -134,15 +129,15 @@ void NesDebugger::ProcessInstruction()
|
|||
_step->Break(BreakSource::CpuStep);
|
||||
}
|
||||
|
||||
_prevOpCode = value;
|
||||
_prevOpCode = opCode;
|
||||
_prevProgramCounter = pc;
|
||||
|
||||
_step->ProcessCpuExec();
|
||||
|
||||
if(_settings->CheckDebuggerFlag(DebuggerFlags::NesDebuggerEnabled)) {
|
||||
if(value == 0x00 && _settings->CheckDebuggerFlag(DebuggerFlags::NesBreakOnBrk)) {
|
||||
if(opCode == 0x00 && _settings->CheckDebuggerFlag(DebuggerFlags::NesBreakOnBrk)) {
|
||||
_step->Break(BreakSource::BreakOnBrk);
|
||||
} else if(_settings->CheckDebuggerFlag(DebuggerFlags::NesBreakOnUnofficialOpCode) && NesDisUtils::IsOpUnofficial(value)) {
|
||||
} else if(_settings->CheckDebuggerFlag(DebuggerFlags::NesBreakOnUnofficialOpCode) && NesDisUtils::IsOpUnofficial(opCode)) {
|
||||
_step->Break(BreakSource::BreakOnUnofficialOpCode);
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +273,11 @@ void NesDebugger::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool
|
|||
AddressInfo src = _mapper->GetAbsoluteAddress(_prevProgramCounter);
|
||||
AddressInfo ret = _mapper->GetAbsoluteAddress(originalPc);
|
||||
AddressInfo dest = _mapper->GetAbsoluteAddress(currentPc);
|
||||
|
||||
|
||||
if(dest.Type == MemoryType::NesPrgRom && dest.Address >= 0) {
|
||||
_codeDataLogger->SetCode(dest.Address, CdlFlags::SubEntryPoint);
|
||||
}
|
||||
|
||||
_debugger->InternalProcessInterrupt(
|
||||
CpuType::Nes, *this, *_step.get(),
|
||||
src, _prevProgramCounter, dest, currentPc, ret, originalPc, forNmi
|
||||
|
|
|
@ -236,6 +236,7 @@ bool NesDisUtils::IsOpUnofficial(uint8_t opCode)
|
|||
bool NesDisUtils::IsUnconditionalJump(uint8_t opCode)
|
||||
{
|
||||
switch(opCode) {
|
||||
case 0x00: //BRK
|
||||
case 0x20: //JSR
|
||||
case 0x40: //RTI
|
||||
case 0x4C: //JMP (Absolute)
|
||||
|
@ -266,6 +267,30 @@ bool NesDisUtils::IsConditionalJump(uint8_t opCode)
|
|||
}
|
||||
}
|
||||
|
||||
CdlFlags::CdlFlags NesDisUtils::GetOpFlags(uint8_t opCode, uint16_t pc, uint16_t prevPc)
|
||||
{
|
||||
switch(opCode) {
|
||||
case 0x00: //BRK
|
||||
case 0x20: //JSR
|
||||
return CdlFlags::SubEntryPoint;
|
||||
|
||||
case 0x10: //BPL
|
||||
case 0x30: //BMI
|
||||
case 0x4C: //JMP (Absolute)
|
||||
case 0x50: //BVC
|
||||
case 0x6C: //JMP (Indirect)
|
||||
case 0x70: //BVS
|
||||
case 0x90: //BCC
|
||||
case 0xB0: //BCS
|
||||
case 0xD0: //BNE
|
||||
case 0xF0: //BEQ
|
||||
return pc != prevPc + NesDisUtils::GetOpSize(opCode) ? CdlFlags::JumpTarget : CdlFlags::None;
|
||||
|
||||
default:
|
||||
return CdlFlags::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool NesDisUtils::IsJumpToSub(uint8_t opCode)
|
||||
{
|
||||
return opCode == 0x20 || opCode == 0x00; //JSR, BRK
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Debugger/DebugTypes.h"
|
||||
|
||||
class DisassemblyInfo;
|
||||
class LabelManager;
|
||||
|
@ -24,6 +25,7 @@ public:
|
|||
static bool IsOpUnofficial(uint8_t opCode);
|
||||
static bool IsUnconditionalJump(uint8_t opCode);
|
||||
static bool IsConditionalJump(uint8_t opCode);
|
||||
static CdlFlags::CdlFlags GetOpFlags(uint8_t opCode, uint16_t pc, uint16_t prevPc);
|
||||
static bool IsJumpToSub(uint8_t opCode);
|
||||
static bool IsReturnInstruction(uint8_t opCode);
|
||||
};
|
||||
|
|
|
@ -95,25 +95,9 @@ uint8_t* NesMemoryManager::GetInternalRAM()
|
|||
return _internalRAM;
|
||||
}
|
||||
|
||||
uint8_t NesMemoryManager::DebugRead(uint16_t addr, bool disableSideEffects)
|
||||
uint8_t NesMemoryManager::DebugRead(uint16_t addr)
|
||||
{
|
||||
uint8_t value = 0x00;
|
||||
if(addr <= 0x1FFF) {
|
||||
value = _ramReadHandlers[addr]->ReadRam(addr);
|
||||
} else {
|
||||
INesMemoryHandler* handler = _ramReadHandlers[addr];
|
||||
if(handler) {
|
||||
if(disableSideEffects) {
|
||||
value = handler->PeekRam(addr);
|
||||
} else {
|
||||
value = handler->ReadRam(addr);
|
||||
}
|
||||
} else {
|
||||
//Fake open bus
|
||||
value = addr >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t value = _ramReadHandlers[addr]->PeekRam(addr);
|
||||
if(_cheatManager->HasCheats<CpuType::Nes>()) {
|
||||
_cheatManager->ApplyCheat<CpuType::Nes>(addr, value);
|
||||
}
|
||||
|
|
|
@ -49,15 +49,12 @@ class NesMemoryManager : public ISerializable
|
|||
void RegisterWriteHandler(INesMemoryHandler* handler, uint32_t start, uint32_t end);
|
||||
void UnregisterIODevice(INesMemoryHandler* handler);
|
||||
|
||||
uint8_t DebugRead(uint16_t addr, bool disableSideEffects = true);
|
||||
uint8_t DebugRead(uint16_t addr);
|
||||
uint16_t DebugReadWord(uint16_t addr);
|
||||
void DebugWrite(uint16_t addr, uint8_t value, bool disableSideEffects = true);
|
||||
|
||||
uint8_t* GetInternalRAM();
|
||||
|
||||
uint8_t DebugReadVram(uint16_t addr);
|
||||
void DebugWriteVram(uint16_t addr, uint8_t value);
|
||||
|
||||
uint8_t Read(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read);
|
||||
void Write(uint16_t addr, uint8_t value, MemoryOperationType operationType);
|
||||
|
||||
|
|
|
@ -76,32 +76,27 @@ void PceDebugger::Reset()
|
|||
{
|
||||
_enableBreakOnUninitRead = true;
|
||||
_callstackManager.reset(new CallstackManager(_debugger));
|
||||
_prevOpCode = 0xFF;
|
||||
_prevOpCode = 0x01;
|
||||
}
|
||||
|
||||
void PceDebugger::ProcessInstruction()
|
||||
{
|
||||
PceCpuState& state = _cpu->GetState();
|
||||
uint16_t addr = state.PC;
|
||||
uint8_t value = _memoryManager->DebugRead(addr);
|
||||
AddressInfo addressInfo = _memoryManager->GetAbsoluteAddress(addr);
|
||||
MemoryOperationInfo operation(addr, value, MemoryOperationType::ExecOpCode, MemoryType::PceMemory);
|
||||
uint16_t pc = state.PC;
|
||||
uint8_t opCode = _memoryManager->DebugRead(pc);
|
||||
AddressInfo addressInfo = _memoryManager->GetAbsoluteAddress(pc);
|
||||
MemoryOperationInfo operation(pc, opCode, MemoryOperationType::ExecOpCode, MemoryType::PceMemory);
|
||||
|
||||
bool needDisassemble = _traceLogger->IsEnabled() || _settings->CheckDebuggerFlag(DebuggerFlags::PceDebuggerEnabled);
|
||||
if(addressInfo.Address >= 0) {
|
||||
if(addressInfo.Type == MemoryType::PcePrgRom) {
|
||||
if(PceDisUtils::IsJumpToSub(_prevOpCode)) {
|
||||
_codeDataLogger->SetCode<CdlFlags::SubEntryPoint>(addressInfo.Address);
|
||||
} else {
|
||||
_codeDataLogger->SetCode(addressInfo.Address);
|
||||
}
|
||||
_codeDataLogger->SetCode(addressInfo.Address, PceDisUtils::GetOpFlags(_prevOpCode, pc, _prevProgramCounter));
|
||||
}
|
||||
if(needDisassemble) {
|
||||
_disassembler->BuildCache(addressInfo, 0, CpuType::Pce);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pc = state.PC;
|
||||
if(PceDisUtils::IsJumpToSub(_prevOpCode)) {
|
||||
//JSR
|
||||
uint8_t opSize = PceDisUtils::GetOpSize(_prevOpCode);
|
||||
|
@ -119,15 +114,15 @@ void PceDebugger::ProcessInstruction()
|
|||
_step->Break(BreakSource::CpuStep);
|
||||
}
|
||||
|
||||
_prevOpCode = value;
|
||||
_prevOpCode = opCode;
|
||||
_prevProgramCounter = pc;
|
||||
|
||||
_step->ProcessCpuExec();
|
||||
|
||||
if(_settings->CheckDebuggerFlag(DebuggerFlags::PceDebuggerEnabled)) {
|
||||
if(value == 0x00 && _settings->CheckDebuggerFlag(DebuggerFlags::PceBreakOnBrk)) {
|
||||
if(opCode == 0x00 && _settings->CheckDebuggerFlag(DebuggerFlags::PceBreakOnBrk)) {
|
||||
_step->Break(BreakSource::BreakOnBrk);
|
||||
} else if(_settings->CheckDebuggerFlag(DebuggerFlags::PceBreakOnUnofficialOpCode) && PceDisUtils::IsOpUnofficial(value)) {
|
||||
} else if(_settings->CheckDebuggerFlag(DebuggerFlags::PceBreakOnUnofficialOpCode) && PceDisUtils::IsOpUnofficial(opCode)) {
|
||||
_step->Break(BreakSource::BreakOnUnofficialOpCode);
|
||||
}
|
||||
}
|
||||
|
@ -254,6 +249,10 @@ void PceDebugger::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool
|
|||
AddressInfo ret = _memoryManager->GetAbsoluteAddress(originalPc);
|
||||
AddressInfo dest = _memoryManager->GetAbsoluteAddress(currentPc);
|
||||
|
||||
if(dest.Type == MemoryType::PcePrgRom && dest.Address >= 0) {
|
||||
_codeDataLogger->SetCode(dest.Address, CdlFlags::SubEntryPoint);
|
||||
}
|
||||
|
||||
_debugger->InternalProcessInterrupt(
|
||||
CpuType::Pce, *this, *_step.get(),
|
||||
src, _prevProgramCounter, dest, currentPc, ret, originalPc, forNmi
|
||||
|
|
|
@ -50,7 +50,7 @@ class PceDebugger final : public IDebugger
|
|||
unique_ptr<PceVdcTools> _ppuTools;
|
||||
|
||||
bool _enableBreakOnUninitRead = false;
|
||||
uint8_t _prevOpCode = 0xFF;
|
||||
uint8_t _prevOpCode = 0x01;
|
||||
uint32_t _prevProgramCounter = 0;
|
||||
|
||||
unique_ptr<DummyPceCpu> _dummyCpu;
|
||||
|
|
|
@ -275,6 +275,37 @@ bool PceDisUtils::IsConditionalJump(uint8_t opCode)
|
|||
}
|
||||
}
|
||||
|
||||
CdlFlags::CdlFlags PceDisUtils::GetOpFlags(uint8_t opCode, uint16_t pc, uint16_t prevPc)
|
||||
{
|
||||
switch(opCode) {
|
||||
case 0x00: //BRK
|
||||
case 0x20: //JSR
|
||||
case 0x44: //BSR
|
||||
return CdlFlags::SubEntryPoint;
|
||||
|
||||
case 0x10: //BPL
|
||||
case 0x30: //BMI
|
||||
case 0x4C: //JMP (Absolute)
|
||||
case 0x50: //BVC
|
||||
case 0x6C: //JMP (Indirect)
|
||||
case 0x70: //BVS
|
||||
case 0x7C: //JMP (Absolute,X)
|
||||
case 0x80: //BRA
|
||||
case 0x90: //BCC
|
||||
case 0xB0: //BCS
|
||||
case 0xD0: //BNE
|
||||
case 0xF0: //BEQ
|
||||
case 0x0F: case 0x1F: case 0x2F: case 0x3F: //BBR
|
||||
case 0x4F: case 0x5F: case 0x6F: case 0x7F: //BBR
|
||||
case 0x8F: case 0x9F: case 0xAF: case 0xBF: //BBS
|
||||
case 0xCF: case 0xDF: case 0xEF: case 0xFF: //BBS
|
||||
return pc != prevPc + PceDisUtils::GetOpSize(opCode) ? CdlFlags::JumpTarget : CdlFlags::None;
|
||||
|
||||
default:
|
||||
return CdlFlags::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool PceDisUtils::IsJumpToSub(uint8_t opCode)
|
||||
{
|
||||
return opCode == 0x20 || opCode == 0x44 || opCode == 0x00; //JSR, BSR, BRK
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Debugger/DebugTypes.h"
|
||||
|
||||
class DisassemblyInfo;
|
||||
class LabelManager;
|
||||
|
@ -25,5 +26,6 @@ public:
|
|||
static bool IsConditionalJump(uint8_t opCode);
|
||||
static bool IsJumpToSub(uint8_t opCode);
|
||||
static bool IsReturnInstruction(uint8_t opCode);
|
||||
static CdlFlags::CdlFlags GetOpFlags(uint8_t opCode, uint16_t pc, uint16_t prevPc);
|
||||
static bool IsOpUnofficial(uint8_t opCode);
|
||||
};
|
||||
|
|
|
@ -50,8 +50,8 @@ void Cx4Debugger::ProcessInstruction()
|
|||
MemoryOperationInfo operation(addr, value, MemoryOperationType::ExecOpCode, MemoryType::Cx4Memory);
|
||||
|
||||
if(addressInfo.Type == MemoryType::SnesPrgRom) {
|
||||
_codeDataLogger->SetSnesCode<SnesCdlFlags::Cx4>(addressInfo.Address);
|
||||
_codeDataLogger->SetSnesCode<SnesCdlFlags::Cx4>(addressInfo.Address + 1);
|
||||
_codeDataLogger->SetCode<SnesCdlFlags::Cx4>(addressInfo.Address);
|
||||
_codeDataLogger->SetCode<SnesCdlFlags::Cx4>(addressInfo.Address + 1);
|
||||
}
|
||||
|
||||
if(_settings->CheckDebuggerFlag(DebuggerFlags::Cx4DebuggerEnabled)) {
|
||||
|
|
|
@ -50,7 +50,7 @@ void GsuDebugger::ProcessInstruction()
|
|||
MemoryOperationInfo operation(addr, state.ProgramReadBuffer, MemoryOperationType::ExecOpCode, MemoryType::GsuMemory);
|
||||
|
||||
if(addressInfo.Type == MemoryType::SnesPrgRom) {
|
||||
_codeDataLogger->SetSnesCode<SnesCdlFlags::Gsu>(addressInfo.Address);
|
||||
_codeDataLogger->SetCode<SnesCdlFlags::Gsu>(addressInfo.Address);
|
||||
}
|
||||
|
||||
if(_settings->CheckDebuggerFlag(DebuggerFlags::GsuDebuggerEnabled)) {
|
||||
|
|
|
@ -34,17 +34,6 @@ private:
|
|||
public:
|
||||
using CodeDataLogger::CodeDataLogger;
|
||||
|
||||
void SetSnesCode(int32_t absoluteAddr, uint8_t flags)
|
||||
{
|
||||
_cdlData[absoluteAddr] |= CdlFlags::Code | flags;
|
||||
}
|
||||
|
||||
template<uint8_t flags>
|
||||
void SetSnesCode(int32_t absoluteAddr)
|
||||
{
|
||||
_cdlData[absoluteAddr] |= CdlFlags::Code | flags;
|
||||
}
|
||||
|
||||
void RebuildPrgCache(Disassembler* dis) override
|
||||
{
|
||||
//TODO GSU flags
|
||||
|
|
|
@ -123,19 +123,15 @@ void SnesDebugger::ProcessConfigChange()
|
|||
void SnesDebugger::ProcessInstruction()
|
||||
{
|
||||
SnesCpuState& state = GetCpuState();
|
||||
uint32_t addr = (state.K << 16) | state.PC;
|
||||
AddressInfo addressInfo = _memoryMappings->GetAbsoluteAddress(addr);
|
||||
uint8_t value = _memoryManager->Peek(addr);
|
||||
MemoryOperationInfo operation(addr, value, MemoryOperationType::ExecOpCode, MemoryType::SnesMemory);
|
||||
uint32_t pc = (state.K << 16) | state.PC;
|
||||
AddressInfo addressInfo = _memoryMappings->GetAbsoluteAddress(pc);
|
||||
uint8_t opCode = _memoryManager->Peek(pc);
|
||||
MemoryOperationInfo operation(pc, opCode, MemoryOperationType::ExecOpCode, MemoryType::SnesMemory);
|
||||
|
||||
if(addressInfo.Address >= 0) {
|
||||
uint8_t cpuFlags = state.PS & (ProcFlags::IndexMode8 | ProcFlags::MemoryMode8);
|
||||
if(addressInfo.Type == MemoryType::SnesPrgRom) {
|
||||
uint8_t flags = CdlFlags::Code | cpuFlags;
|
||||
if(SnesDisUtils::IsJumpToSub(_prevOpCode)) {
|
||||
flags |= CdlFlags::SubEntryPoint;
|
||||
}
|
||||
_cdl->SetSnesCode(addressInfo.Address, flags);
|
||||
_cdl->SetCode(addressInfo.Address, SnesDisUtils::GetOpFlags(_prevOpCode, pc, _prevProgramCounter) | cpuFlags);
|
||||
}
|
||||
if(_traceLogger->IsEnabled() || _debuggerEnabled) {
|
||||
_disassembler->BuildCache(addressInfo, cpuFlags, _cpuType);
|
||||
|
@ -148,26 +144,26 @@ void SnesDebugger::ProcessInstruction()
|
|||
uint32_t returnPc = (_prevProgramCounter & 0xFF0000) | (((_prevProgramCounter & 0xFFFF) + opSize) & 0xFFFF);
|
||||
AddressInfo srcAddress = _memoryMappings->GetAbsoluteAddress(_prevProgramCounter);
|
||||
AddressInfo retAddress = _memoryMappings->GetAbsoluteAddress(returnPc);
|
||||
_callstackManager->Push(srcAddress, _prevProgramCounter, addressInfo, addr, retAddress, returnPc, StackFrameFlags::None);
|
||||
_callstackManager->Push(srcAddress, _prevProgramCounter, addressInfo, pc, retAddress, returnPc, StackFrameFlags::None);
|
||||
} else if(SnesDisUtils::IsReturnInstruction(_prevOpCode)) {
|
||||
//RTS, RTL, RTI
|
||||
_callstackManager->Pop(addressInfo, addr);
|
||||
_callstackManager->Pop(addressInfo, pc);
|
||||
}
|
||||
|
||||
if(_step->BreakAddress == (int32_t)addr && (SnesDisUtils::IsReturnInstruction(_prevOpCode) || _prevOpCode == 0x44 || _prevOpCode == 0x54)) {
|
||||
if(_step->BreakAddress == (int32_t)pc && (SnesDisUtils::IsReturnInstruction(_prevOpCode) || _prevOpCode == 0x44 || _prevOpCode == 0x54)) {
|
||||
//RTS/RTL/RTI found, if we're on the expected return address, break immediately (for step over/step out)
|
||||
//Also used for MVN/MVP
|
||||
_step->Break(BreakSource::CpuStep);
|
||||
}
|
||||
|
||||
_prevOpCode = value;
|
||||
_prevProgramCounter = addr;
|
||||
_prevOpCode = opCode;
|
||||
_prevProgramCounter = pc;
|
||||
|
||||
_step->ProcessCpuExec();
|
||||
|
||||
if(_debuggerEnabled) {
|
||||
//Break on BRK/STP/WDM/COP
|
||||
switch(value) {
|
||||
switch(opCode) {
|
||||
case 0x00: if(_settings->CheckDebuggerFlag(DebuggerFlags::BreakOnBrk)) { _step->Break(BreakSource::BreakOnBrk); } break;
|
||||
case 0x02: if(_settings->CheckDebuggerFlag(DebuggerFlags::BreakOnCop)) { _step->Break(BreakSource::BreakOnCop); } break;
|
||||
case 0x42: if(_settings->CheckDebuggerFlag(DebuggerFlags::BreakOnWdm)) { _step->Break(BreakSource::BreakOnWdm); } break;
|
||||
|
@ -208,7 +204,7 @@ void SnesDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
|
|||
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
|
||||
} else if(type == MemoryOperationType::ExecOperand) {
|
||||
if(addressInfo.Type == MemoryType::SnesPrgRom && addressInfo.Address >= 0) {
|
||||
_cdl->SetSnesCode(addressInfo.Address, (state.PS & (SnesCdlFlags::IndexMode8 | SnesCdlFlags::MemoryMode8)));
|
||||
_cdl->SetCode(addressInfo.Address, (state.PS & (SnesCdlFlags::IndexMode8 | SnesCdlFlags::MemoryMode8)));
|
||||
}
|
||||
if(_traceLogger->IsEnabled()) {
|
||||
_traceLogger->LogNonExec(operation);
|
||||
|
@ -299,6 +295,10 @@ void SnesDebugger::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, boo
|
|||
AddressInfo ret = _memoryMappings->GetAbsoluteAddress(originalPc);
|
||||
AddressInfo dest = _memoryMappings->GetAbsoluteAddress(currentPc);
|
||||
|
||||
if(dest.Type == MemoryType::SnesPrgRom && dest.Address >= 0) {
|
||||
_codeDataLogger->SetCode(dest.Address, CdlFlags::SubEntryPoint);
|
||||
}
|
||||
|
||||
_debugger->InternalProcessInterrupt(
|
||||
_cpuType, *this, *_step.get(),
|
||||
src, _prevProgramCounter, dest, currentPc, ret, originalPc, forNmi
|
||||
|
|
|
@ -216,6 +216,37 @@ bool SnesDisUtils::IsConditionalJump(uint8_t opCode)
|
|||
}
|
||||
}
|
||||
|
||||
CdlFlags::CdlFlags SnesDisUtils::GetOpFlags(uint8_t opCode, uint32_t pc, uint32_t prevPc)
|
||||
{
|
||||
switch(opCode) {
|
||||
case 0x00: //BRK
|
||||
case 0x02: //COP
|
||||
case 0x20: //JSR
|
||||
case 0x22: //JSR
|
||||
case 0xFC: //JSR
|
||||
return CdlFlags::SubEntryPoint;
|
||||
|
||||
case 0x10: //BPL
|
||||
case 0x30: //BMI
|
||||
case 0x50: //BVC
|
||||
case 0x70: //BVS
|
||||
case 0x90: //BCC
|
||||
case 0xB0: //BCS
|
||||
case 0xD0: //BNE
|
||||
case 0xF0: //BEQ
|
||||
case 0x4C: //JMP
|
||||
case 0x5C: //JMP
|
||||
case 0x6C: //JMP
|
||||
case 0x7C: //JMP
|
||||
case 0x80: //BRA
|
||||
case 0xDC: //JMP
|
||||
return pc != prevPc + SnesDisUtils::GetOpSize(opCode, 0) ? CdlFlags::JumpTarget : CdlFlags::None;
|
||||
|
||||
default:
|
||||
return CdlFlags::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool SnesDisUtils::IsJumpToSub(uint8_t opCode)
|
||||
{
|
||||
return opCode == 0x20 || opCode == 0x22 || opCode == 0xFC; //JSR, JSL
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Debugger/DebugTypes.h"
|
||||
|
||||
class DisassemblyInfo;
|
||||
class SnesConsole;
|
||||
|
@ -26,6 +27,7 @@ public:
|
|||
static uint8_t GetOpSize(uint8_t opCode, uint8_t flags);
|
||||
static bool IsUnconditionalJump(uint8_t opCode);
|
||||
static bool IsConditionalJump(uint8_t opCode);
|
||||
static CdlFlags::CdlFlags GetOpFlags(uint8_t opCode, uint32_t pc, uint32_t prevPc);
|
||||
static bool IsJumpToSub(uint8_t opCode);
|
||||
static bool IsReturnInstruction(uint8_t opCode);
|
||||
static int32_t GetEffectiveAddress(DisassemblyInfo &info, SnesConsole* console, SnesCpuState &state, CpuType type);
|
||||
|
|
|
@ -769,6 +769,8 @@ enum class DebuggerFlags : uint64_t
|
|||
BreakOnStp = (1 << 3),
|
||||
BreakOnUninitRead = (1 << 4),
|
||||
|
||||
ShowJumpLabels = (1 << 5),
|
||||
|
||||
ShowVerifiedData = (1 << 8),
|
||||
DisassembleVerifiedData = (1 << 9),
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace Mesen.Config
|
|||
|
||||
[Reactive] public bool ShowByteCode { get; set; } = false;
|
||||
[Reactive] public bool UseLowerCaseDisassembly { get; set; } = false;
|
||||
|
||||
[Reactive] public bool ShowJumpLabels { get; set; } = false;
|
||||
|
||||
[Reactive] public SnesDebuggerConfig Snes { get; set; } = new();
|
||||
[Reactive] public NesDebuggerConfig Nes { get; set; } = new();
|
||||
|
@ -47,6 +49,7 @@ namespace Mesen.Config
|
|||
[Reactive] public CodeDisplayMode UnidentifiedBlockDisplay { get; set; } = CodeDisplayMode.Hide;
|
||||
[Reactive] public CodeDisplayMode VerifiedDataDisplay { get; set; } = CodeDisplayMode.Hide;
|
||||
|
||||
//TODO remove?
|
||||
[Reactive] public bool UseAltSpcOpNames { get; set; } = false;
|
||||
|
||||
[Reactive] public int BreakOnValue { get; set; } = 0;
|
||||
|
@ -56,8 +59,6 @@ namespace Mesen.Config
|
|||
[Reactive] public bool ShowSelectionLength { get; set; } = false;
|
||||
[Reactive] public WatchFormatStyle WatchFormat { get; set; } = WatchFormatStyle.Hex;
|
||||
|
||||
[Reactive] public bool ShowCommentsInLabelList { get; set; } = true;
|
||||
|
||||
[Reactive] public Color CodeOpcodeColor { get; set; } = Color.FromRgb(22, 37, 37);
|
||||
[Reactive] public Color CodeLabelDefinitionColor { get; set; } = Colors.Blue;
|
||||
[Reactive] public Color CodeImmediateColor { get; set; } = Colors.Chocolate;
|
||||
|
@ -86,6 +87,8 @@ namespace Mesen.Config
|
|||
Pce.ApplyConfig();
|
||||
|
||||
ConfigApi.SetDebuggerFlag(DebuggerFlags.BreakOnUninitRead, BreakOnUninitRead);
|
||||
|
||||
ConfigApi.SetDebuggerFlag(DebuggerFlags.ShowJumpLabels, ShowJumpLabels);
|
||||
|
||||
ConfigApi.SetDebuggerFlag(DebuggerFlags.ShowUnidentifiedData, UnidentifiedBlockDisplay == CodeDisplayMode.Show);
|
||||
ConfigApi.SetDebuggerFlag(DebuggerFlags.DisassembleUnidentifiedData, UnidentifiedBlockDisplay == CodeDisplayMode.Disassemble);
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
IsChecked="{CompiledBinding Config.ShowByteCode}"
|
||||
Content="{l:Translate chkShowByteCode}"
|
||||
/>
|
||||
<CheckBox
|
||||
IsChecked="{CompiledBinding Config.ShowJumpLabels}"
|
||||
Content="{l:Translate chkShowJumpLabels}"
|
||||
/>
|
||||
<CheckBox
|
||||
IsChecked="{CompiledBinding Config.UseLowerCaseDisassembly}"
|
||||
Content="{l:Translate chkUseLowerCaseDisassembly}"
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace Mesen.Interop
|
|||
BreakOnStp = (1 << 3),
|
||||
BreakOnUninitRead = (1 << 4),
|
||||
|
||||
ShowJumpLabels = (1 << 5),
|
||||
|
||||
ShowVerifiedData = (1 << 8),
|
||||
DisassembleVerifiedData = (1 << 9),
|
||||
|
||||
|
|
|
@ -962,6 +962,7 @@
|
|||
<Control ID="lblUnidentifiedBlock">Unidentified blocks:</Control>
|
||||
<Control ID="chkShowByteCode">Show byte code</Control>
|
||||
<Control ID="chkUseLowerCaseDisassembly">Use lower case</Control>
|
||||
<Control ID="chkShowJumpLabels">Show jump/sub labels</Control>
|
||||
|
||||
<Control ID="lblBreakOptions">Break on...</Control>
|
||||
<Control ID="chkBreakOnBrk">BRK</Control>
|
||||
|
|
2
NewUI/ThirdParty/DataBox/DataBox.cs
vendored
2
NewUI/ThirdParty/DataBox/DataBox.cs
vendored
|
@ -74,7 +74,7 @@ public class DataBox : TemplatedControl
|
|||
AvaloniaProperty.Register<DataBox, IBrush>(nameof(VerticalGridLinesBrush));
|
||||
|
||||
private IEnumerable _items = Array.Empty<object?>();
|
||||
private ISelectionModel _selection = new SelectionModel<object?>();
|
||||
private ISelectionModel? _selection = new SelectionModel<object?>();
|
||||
|
||||
private AvaloniaList<DataBoxColumn> _columns;
|
||||
private ScrollViewer? _headersPresenterScrollViewer;
|
||||
|
|
Loading…
Add table
Reference in a new issue