Skip to content

Commit

Permalink
Debugger: Breakpoints now respect HALT/USER CPU mode
Browse files Browse the repository at this point in the history
  • Loading branch information
nzeemin committed Nov 17, 2024
1 parent 6736dc6 commit 78c3e73
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 56 deletions.
26 changes: 18 additions & 8 deletions emulator/ConsoleView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,11 +599,12 @@ void ConsoleView_CmdStepInto(const ConsoleCommandParams& /*params*/)
void ConsoleView_CmdStepOver(const ConsoleCommandParams& /*params*/)
{
CProcessor* pProc = ConsoleView_GetCurrentProcessor();
bool okHaltMode = pProc->IsHaltMode();

int instrLength = ConsoleView_PrintDisassemble(pProc, pProc->GetPC(), TRUE, FALSE);
uint16_t bpaddress = (uint16_t)(pProc->GetPC() + instrLength * 2);

Emulator_SetTempCPUBreakpoint(bpaddress);
Emulator_SetTempCPUBreakpoint(bpaddress, okHaltMode);
Emulator_Start();
}
void ConsoleView_CmdRun(const ConsoleCommandParams& /*params*/)
Expand All @@ -613,23 +614,28 @@ void ConsoleView_CmdRun(const ConsoleCommandParams& /*params*/)
void ConsoleView_CmdRunToAddress(const ConsoleCommandParams& params)
{
uint16_t address = params.paramOct1;
CProcessor* pProc = ConsoleView_GetCurrentProcessor();
bool okHaltMode = pProc->IsHaltMode();

Emulator_SetTempCPUBreakpoint(address);
Emulator_SetTempCPUBreakpoint(address, okHaltMode);
Emulator_Start();
}

void ConsoleView_CmdPrintAllBreakpoints(const ConsoleCommandParams& /*params*/)
{
const uint16_t* pbps = Emulator_GetCPUBreakpointList();
if (pbps == nullptr || *pbps == 0177777)
const uint32_t* pbps = Emulator_GetCPUBreakpointList();
if (pbps == nullptr || *pbps == NOBREAKPOINT)
{
ConsoleView_Print(_T(" No breakpoints.\r\n"));
}
else
{
while (*pbps != 0177777)
while (*pbps != NOBREAKPOINT)
{
ConsoleView_PrintFormat(_T(" %06ho\r\n"), *pbps);
uint32_t bpvalue = *pbps;
uint16_t address = bpvalue & 0xffff;
TCHAR huch = (bpvalue & BREAKPOINT_HALT) != 0 ? _T('H') : _T('U');
ConsoleView_PrintFormat(_T(" %c%06ho\r\n"), huch, address);
pbps++;
}
}
Expand All @@ -644,8 +650,10 @@ void ConsoleView_CmdRemoveAllBreakpoints(const ConsoleCommandParams& /*params*/)
void ConsoleView_CmdSetBreakpointAtAddress(const ConsoleCommandParams& params)
{
uint16_t address = params.paramOct1;
CProcessor* pProc = ConsoleView_GetCurrentProcessor();
bool okHaltMode = pProc->IsHaltMode();

bool result = Emulator_AddCPUBreakpoint(address);
bool result = Emulator_AddCPUBreakpoint(address, okHaltMode);
if (!result)
ConsoleView_Print(_T(" Failed to add breakpoint.\r\n"));

Expand All @@ -655,8 +663,10 @@ void ConsoleView_CmdSetBreakpointAtAddress(const ConsoleCommandParams& params)
void ConsoleView_CmdRemoveBreakpointAtAddress(const ConsoleCommandParams& params)
{
uint16_t address = params.paramOct1;
CProcessor* pProc = ConsoleView_GetCurrentProcessor();
bool okHaltMode = pProc->IsHaltMode();

bool result = Emulator_RemoveCPUBreakpoint(address);
bool result = Emulator_RemoveCPUBreakpoint(address, okHaltMode);
if (!result)
ConsoleView_Print(_T(" Failed to remove breakpoint.\r\n"));
DebugView_Redraw();
Expand Down
13 changes: 9 additions & 4 deletions emulator/DebugView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,14 +781,19 @@ void DebugBreaksView_DoDraw(HDC hdc)
int x = cxChar / 2, y = cyLine / 2;
TextOut(hdc, x, y, _T("Breakpts"), 8);

const uint16_t* pbps = Emulator_GetCPUBreakpointList();
if (*pbps != 0177777)
const uint32_t* pbps = Emulator_GetCPUBreakpointList();
if (*pbps != NOBREAKPOINT)
{
x += cxChar;
y += cyLine;
while (*pbps != 0177777)
while (*pbps != NOBREAKPOINT)
{
DrawOctalValue(hdc, x, y, *pbps);
uint32_t bpvalue = *pbps;
uint16_t address = bpvalue & 0xffff;
TCHAR buffer[8];
buffer[0] = (bpvalue & BREAKPOINT_HALT) != 0 ? _T('H') : _T('U');
PrintOctalValue(buffer + 1, address);
TextOut(hdc, x, y, buffer, 7);
y += cyLine;
pbps++;
}
Expand Down
12 changes: 8 additions & 4 deletions emulator/DisasmView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,17 +267,20 @@ void DisasmView_OnLButtonDown(int mousex, int mousey)
if (pLineItem->type == LINETYPE_NONE)
return;

CProcessor* pProc = g_pBoard->GetCPU();
bool okHaltMode = pProc->IsHaltMode();

// Try to and add/remove breakpoint for the line
uint16_t address = pLineItem->address;
if (!Emulator_IsBreakpoint(address))
if (!Emulator_IsBreakpoint(address, okHaltMode))
{
bool result = Emulator_AddCPUBreakpoint(address);
bool result = Emulator_AddCPUBreakpoint(address, okHaltMode);
if (!result)
AlertWarningFormat(_T("Failed to add breakpoint at %06ho."), address);
}
else
{
bool result = Emulator_RemoveCPUBreakpoint(address);
bool result = Emulator_RemoveCPUBreakpoint(address, okHaltMode);
if (!result)
AlertWarningFormat(_T("Failed to remove breakpoint at %06ho."), address);
}
Expand Down Expand Up @@ -747,6 +750,7 @@ int DisasmView_DrawDisassemble(HDC hdc, const CProcessor* pProc, uint16_t curren
::SetTextColor(hdc, colorText);

uint16_t proccurrent = pProc->GetPC();
bool prochalt = pProc->IsHaltMode();

// Draw breakpoint zone
COLORREF colorBreakptZone = Settings_GetColor(ColorDebugBreakptZone);
Expand Down Expand Up @@ -788,7 +792,7 @@ int DisasmView_DrawDisassemble(HDC hdc, const CProcessor* pProc, uint16_t curren
continue;
}

if (Emulator_IsBreakpoint(address)) // Breakpoint
if (Emulator_IsBreakpoint(address, prochalt)) // Breakpoint
{
DisasmView_DrawBreakpoint(hdc, cxChar / 2, y, cyLine);
}
Expand Down
75 changes: 44 additions & 31 deletions emulator/Emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ NeonConfiguration g_nEmulatorConfiguration; // Current configuration
bool g_okEmulatorRunning = false;

int m_wEmulatorCPUBpsCount = 0;
uint16_t m_EmulatorCPUBps[MAX_BREAKPOINTCOUNT + 1];
uint16_t m_wEmulatorTempCPUBreakpoint = 0177777;
uint32_t m_EmulatorCPUBps[MAX_BREAKPOINTCOUNT + 1];
uint32_t m_wEmulatorTempCPUBreakpoint = 0177777;
int m_wEmulatorWatchesCount = 0;
uint16_t m_EmulatorWatches[MAX_BREAKPOINTCOUNT];

Expand Down Expand Up @@ -110,7 +110,7 @@ bool Emulator_Init()
m_wEmulatorCPUBpsCount = 0;
for (int i = 0; i <= MAX_BREAKPOINTCOUNT; i++)
{
m_EmulatorCPUBps[i] = 0177777;
m_EmulatorCPUBps[i] = NOBREAKPOINT;
}
m_wEmulatorWatchesCount = 0;
for (int i = 0; i < MAX_WATCHESCOUNT; i++)
Expand Down Expand Up @@ -195,7 +195,7 @@ void Emulator_Stop()
{
g_okEmulatorRunning = false;

Emulator_SetTempCPUBreakpoint(0177777);
Emulator_SetTempCPUBreakpoint(0177777, false);

if (m_fpEmulatorSerialOut != nullptr)
::fflush(m_fpEmulatorSerialOut);
Expand All @@ -222,99 +222,108 @@ void Emulator_Reset()
MainWindow_UpdateAllViews();
}

bool Emulator_AddCPUBreakpoint(uint16_t address)
bool Emulator_AddCPUBreakpoint(uint16_t address, bool ishalt)
{
if (m_wEmulatorCPUBpsCount == MAX_BREAKPOINTCOUNT - 1 || address == 0177777)
if (m_wEmulatorCPUBpsCount == MAX_BREAKPOINTCOUNT - 1)
return false;
uint32_t bpvalue = ((uint32_t)address) | (ishalt ? BREAKPOINT_HALT : 0);
for (int i = 0; i < m_wEmulatorCPUBpsCount; i++) // Check if the BP exists
{
if (m_EmulatorCPUBps[i] == address)
if (m_EmulatorCPUBps[i] == bpvalue)
return false; // Already in the list
}
for (int i = 0; i < MAX_BREAKPOINTCOUNT; i++) // Put in the first empty cell
{
if (m_EmulatorCPUBps[i] > address) // found the place
if (m_EmulatorCPUBps[i] > bpvalue) // found the place
{
memcpy(m_EmulatorCPUBps + i + 1, m_EmulatorCPUBps + i, sizeof(uint16_t) * (m_wEmulatorCPUBpsCount - i));
m_EmulatorCPUBps[i] = address;
m_EmulatorCPUBps[i] = bpvalue;
break;
}
if (m_EmulatorCPUBps[i] == 0177777) // found empty place
if (m_EmulatorCPUBps[i] == NOBREAKPOINT) // found empty place
{
m_EmulatorCPUBps[i] = address;
m_EmulatorCPUBps[i] = bpvalue;
break;
}
}
m_wEmulatorCPUBpsCount++;
return true;
}
bool Emulator_RemoveCPUBreakpoint(uint16_t address)
bool Emulator_RemoveCPUBreakpoint(uint16_t address, bool ishalt)
{
if (m_wEmulatorCPUBpsCount == 0 || address == 0177777)
uint32_t bpvalue = ((uint32_t)address) | (ishalt ? BREAKPOINT_HALT : 0);
return Emulator_RemoveCPUBreakpoint(bpvalue);
}
bool Emulator_RemoveCPUBreakpoint(uint32_t bpvalue)
{
if (m_wEmulatorCPUBpsCount == 0)
return false;
for (int i = 0; i < MAX_BREAKPOINTCOUNT; i++)
{
if (m_EmulatorCPUBps[i] == address)
if (m_EmulatorCPUBps[i] == bpvalue)
{
m_EmulatorCPUBps[i] = 0177777;
m_EmulatorCPUBps[i] = NOBREAKPOINT;
m_wEmulatorCPUBpsCount--;
if (m_wEmulatorCPUBpsCount > i) // fill the hole
{
memcpy(m_EmulatorCPUBps + i, m_EmulatorCPUBps + i + 1, sizeof(uint16_t) * (m_wEmulatorCPUBpsCount - i));
m_EmulatorCPUBps[m_wEmulatorCPUBpsCount] = 0177777;
memcpy(m_EmulatorCPUBps + i, m_EmulatorCPUBps + i + 1, sizeof(uint32_t) * (m_wEmulatorCPUBpsCount - i));
m_EmulatorCPUBps[m_wEmulatorCPUBpsCount] = NOBREAKPOINT;
}
return true;
}
}
return false;
}
void Emulator_SetTempCPUBreakpoint(uint16_t address)
void Emulator_SetTempCPUBreakpoint(uint16_t address, bool ishalt)
{
if (m_wEmulatorTempCPUBreakpoint != 0177777)
if (m_wEmulatorTempCPUBreakpoint != NOBREAKPOINT)
Emulator_RemoveCPUBreakpoint(m_wEmulatorTempCPUBreakpoint);
if (address == 0177777)
{
m_wEmulatorTempCPUBreakpoint = 0177777;
m_wEmulatorTempCPUBreakpoint = NOBREAKPOINT;
return;
}
uint32_t bpvalue = ((uint32_t)address) | (ishalt ? BREAKPOINT_HALT : 0);
for (int i = 0; i < MAX_BREAKPOINTCOUNT; i++)
{
if (m_EmulatorCPUBps[i] == address)
if (m_EmulatorCPUBps[i] == bpvalue)
return; // We have regular breakpoint with the same address
}
m_wEmulatorTempCPUBreakpoint = address;
m_EmulatorCPUBps[m_wEmulatorCPUBpsCount] = address;
m_wEmulatorTempCPUBreakpoint = bpvalue;
m_EmulatorCPUBps[m_wEmulatorCPUBpsCount] = bpvalue;
m_wEmulatorCPUBpsCount++;
}
const uint16_t* Emulator_GetCPUBreakpointList() { return m_EmulatorCPUBps; }
const uint32_t* Emulator_GetCPUBreakpointList() { return m_EmulatorCPUBps; }
bool Emulator_IsBreakpoint()
{
uint16_t address = g_pBoard->GetCPU()->GetPC();
uint32_t bpvalue = ((uint32_t)address) | (g_pBoard->GetCPU()->IsHaltMode() ? BREAKPOINT_HALT : 0);
if (m_wEmulatorCPUBpsCount > 0)
{
for (int i = 0; i < m_wEmulatorCPUBpsCount; i++)
{
if (address == m_EmulatorCPUBps[i])
if (bpvalue == m_EmulatorCPUBps[i])
return true;
}
}
return false;
}
bool Emulator_IsBreakpoint(uint16_t address)
bool Emulator_IsBreakpoint(uint16_t address, bool ishalt)
{
if (m_wEmulatorCPUBpsCount == 0)
return false;
uint32_t bpvalue = ((uint32_t)address) | (ishalt ? BREAKPOINT_HALT : 0);
for (int i = 0; i < m_wEmulatorCPUBpsCount; i++)
{
if (address == m_EmulatorCPUBps[i])
if (bpvalue == m_EmulatorCPUBps[i])
return true;
}
return false;
}
void Emulator_RemoveAllBreakpoints()
{
for (int i = 0; i < MAX_BREAKPOINTCOUNT; i++)
m_EmulatorCPUBps[i] = 0177777;
m_EmulatorCPUBps[i] = NOBREAKPOINT;
m_wEmulatorCPUBpsCount = 0;
}

Expand Down Expand Up @@ -456,9 +465,13 @@ bool Emulator_SystemFrame()

if (!g_pBoard->SystemFrame())
{
uint16_t pc = g_pBoard->GetCPU()->GetPC();
if (pc != m_wEmulatorTempCPUBreakpoint)
DebugPrintFormat(_T("Breakpoint hit at %06ho\r\n"), pc);
CProcessor* pProc = g_pBoard->GetCPU();
uint16_t address = pProc->GetPC();
bool okHaltMode = pProc->IsHaltMode();
uint32_t bpvalue = ((uint32_t)address) | (okHaltMode ? BREAKPOINT_HALT : 0);
TCHAR huch = (bpvalue & BREAKPOINT_HALT) != 0 ? _T('H') : _T('U');
if (address != m_wEmulatorTempCPUBreakpoint)
DebugPrintFormat(_T("Breakpoint hit at %c%06ho\r\n"), huch, address);
return false;
}

Expand Down
11 changes: 6 additions & 5 deletions emulator/Emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ bool Emulator_Init();
bool Emulator_InitConfiguration(NeonConfiguration configuration);
void Emulator_Done();

bool Emulator_AddCPUBreakpoint(uint16_t address);
bool Emulator_RemoveCPUBreakpoint(uint16_t address);
void Emulator_SetTempCPUBreakpoint(uint16_t address);
const uint16_t* Emulator_GetCPUBreakpointList();
bool Emulator_AddCPUBreakpoint(uint16_t address, bool ishalt);
bool Emulator_RemoveCPUBreakpoint(uint16_t address, bool ishalt);
bool Emulator_RemoveCPUBreakpoint(uint32_t bpvalue);
void Emulator_SetTempCPUBreakpoint(uint16_t address, bool ishalt);
const uint32_t* Emulator_GetCPUBreakpointList();
bool Emulator_IsBreakpoint();
bool Emulator_IsBreakpoint(uint16_t address);
bool Emulator_IsBreakpoint(uint16_t address, bool ishalt);
void Emulator_RemoveAllBreakpoints();

const uint16_t* Emulator_GetWatchList();
Expand Down
5 changes: 3 additions & 2 deletions emulator/emubase/Board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,9 @@ bool CMotherboard::SystemFrame()

if (m_CPUbps != nullptr) // Check for breakpoints
{
const uint16_t* pbps = m_CPUbps;
while (*pbps != 0177777) { if (m_pCPU->GetPC() == *pbps++) return false; }
uint32_t cpucurrent = (m_pCPU->GetPC() & 0xffff) | (m_pCPU->IsHaltMode() ? BREAKPOINT_HALT : 0);
const uint32_t* pbps = m_CPUbps;
while (*pbps != NOBREAKPOINT) { if (cpucurrent == *pbps++) return false; }
}

if ((procticks & 3) == 3) // Every 4th tick
Expand Down
8 changes: 6 additions & 2 deletions emulator/emubase/Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ enum NeonConfiguration
#define PIC_MODE_MASK 255 // Mask for mode bits, usage: (m_PICflags & PIC_MODE_MASK)
#define PIC_CMD_POLL 256 // Flag for Poll Command

// Breakpoints
#define NOBREAKPOINT 0xFFFFFFFF
#define BREAKPOINT_HALT 0x80000000


//////////////////////////////////////////////////////////////////////
// Special key codes
Expand Down Expand Up @@ -177,7 +181,7 @@ class CMotherboard
uint32_t GetRamSizeBytes() const { return m_nRamSizeBytes; }
public: // Debug
void DebugTicks(); // One Debug CPU tick -- use for debug step or debug breakpoint
void SetCPUBreakpoints(const uint16_t* bps) { m_CPUbps = bps; } // Set CPU breakpoint list
void SetCPUBreakpoints(const uint32_t* bps) { m_CPUbps = bps; } // Set CPU breakpoint list
uint32_t GetTrace() const { return m_dwTrace; }
void SetTrace(uint32_t dwTrace);
public: // System control
Expand Down Expand Up @@ -287,7 +291,7 @@ class CMotherboard
void ProcessMouseWrite(uint8_t byte);
void DoSound(uint16_t s0, uint16_t s1, uint16_t s2);
private:
const uint16_t* m_CPUbps; // CPU breakpoint list, ends with 177777 value
const uint32_t* m_CPUbps; // CPU breakpoint list, ends with NOBREAKPOINT value
uint32_t m_dwTrace; // Trace flags
private:
SOUNDGENCALLBACK m_SoundGenCallback;
Expand Down

0 comments on commit 78c3e73

Please sign in to comment.