Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn the break reason into an enum, fix some minor issues #20006

Merged
merged 1 commit into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 45 additions & 13 deletions Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ static std::mutex g_stepMutex;
struct CPUStepCommand {
CPUStepType type;
int stepSize;
const char *reason;
BreakReason reason;
u32 relatedAddr;
bool empty() const {
return type == CPUStepType::None;
}
void clear() {
type = CPUStepType::None;
stepSize = 0;
reason = "";
reason = BreakReason::None;
relatedAddr = 0;
}
};
Expand All @@ -80,13 +80,47 @@ volatile bool coreStatePending = false;

static bool powerSaving = false;
static bool g_breakAfterFrame = false;
static std::string g_breakReason;
static BreakReason g_breakReason = BreakReason::None;

static MIPSExceptionInfo g_exceptionInfo;

// This is called on EmuThread before RunLoop.
static bool Core_ProcessStepping(MIPSDebugInterface *cpu);

BreakReason Core_BreakReason() {
return g_breakReason;
}

const char *BreakReasonToString(BreakReason reason) {
switch (reason) {
case BreakReason::None: return "None";
case BreakReason::DebugBreak: return "cpu.debugbreak";
case BreakReason::DebugStep: return "cpu.stepping";
case BreakReason::DebugStepInto: return "cpu.stepInto";
case BreakReason::UIFocus: return "ui.lost_focus";
case BreakReason::AfterFrame: return "frame.after";
case BreakReason::MemoryException: return "memory.exception";
case BreakReason::CpuException: return "cpu.exception";
case BreakReason::BreakInstruction: return "cpu.breakInstruction";
case BreakReason::SavestateLoad: return "savestate.load";
case BreakReason::SavestateSave: return "savestate.save";
case BreakReason::SavestateRewind: return "savestate.rewind";
case BreakReason::SavestateCrash: return "savestate.crash";
case BreakReason::MemoryBreakpoint: return "memory.breakpoint";
case BreakReason::CpuBreakpoint: return "cpu.breakpoint";
case BreakReason::BreakpointUpdate: return "cpu.breakpoint.update";
case BreakReason::MemoryAccess: return "memory.access"; // ???
case BreakReason::JitBranchDebug: return "jit.branchdebug";
case BreakReason::RABreak: return "ra.break";
case BreakReason::BreakOnBoot: return "ui.boot";
case BreakReason::AddBreakpoint: return "cpu.breakpoint.add";
case BreakReason::FrameAdvance: return "ui.frameAdvance";
case BreakReason::UIPause: return "ui.pause";
case BreakReason::HLEDebugBreak: return "hle.step";
default: return "Unknown";
}
}

void Core_SetGraphicsContext(GraphicsContext *ctx) {
PSP_CoreParameter().graphicsContext = ctx;
}
Expand Down Expand Up @@ -170,6 +204,7 @@ void Core_RunLoopUntil(u64 globalticks) {
mipsr4k.RunLoopUntil(globalticks);
if (g_breakAfterFrame && coreState == CORE_NEXTFRAME) {
g_breakAfterFrame = false;
g_breakReason = BreakReason::AfterFrame;
coreState = CORE_STEPPING_CPU;
}
break; // Will loop around to go to RUNNING_GE or NEXTFRAME, which will exit.
Expand Down Expand Up @@ -376,7 +411,7 @@ static bool Core_ProcessStepping(MIPSDebugInterface *cpu) {
}

// Free-threaded (hm, possibly except tracing).
void Core_Break(const char *reason, u32 relatedAddress) {
void Core_Break(BreakReason reason, u32 relatedAddress) {
if (coreState != CORE_RUNNING_CPU) {
ERROR_LOG(Log::CPU, "Core_Break only works in the CORE_RUNNING_CPU state");
return;
Expand Down Expand Up @@ -405,16 +440,12 @@ void Core_Break(const char *reason, u32 relatedAddress) {
g_cpuStepCommand.reason = reason;
g_cpuStepCommand.relatedAddr = relatedAddress;
steppingCounter++;
_assert_msg_(reason != nullptr, "No reason specified for break");
_assert_msg_(reason != BreakReason::None, "No reason specified for break");
Core_UpdateState(CORE_STEPPING_CPU);
}
System_Notify(SystemNotification::DEBUG_MODE_CHANGE);
}

const std::string &Core_BreakReason() {
return g_breakReason;
}

// Free-threaded (or at least should be)
void Core_Resume() {
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
Expand All @@ -431,6 +462,7 @@ void Core_Resume() {
// Clear the exception if we resume.
Core_ResetException();
coreState = CORE_RUNNING_CPU;
g_breakReason = BreakReason::None;
System_Notify(SystemNotification::DEBUG_MODE_CHANGE);
}

Expand Down Expand Up @@ -523,7 +555,7 @@ void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionTy
e.accessSize = accessSize;
e.stackTrace = stackTrace;
e.pc = pc;
Core_Break("memory.exception", address);
Core_Break(BreakReason::MemoryException, address);
}
}

Expand Down Expand Up @@ -551,7 +583,7 @@ void Core_MemoryExceptionInfo(u32 address, u32 accessSize, u32 pc, MemoryExcepti
e.accessSize = accessSize;
e.stackTrace = stackTrace;
e.pc = pc;
Core_Break("memory.exception", address);
Core_Break(BreakReason::MemoryException, address);
}
}

Expand All @@ -570,7 +602,7 @@ void Core_ExecException(u32 address, u32 pc, ExecExceptionType type) {
e.pc = pc;
// This just records the closest value that could be useful as reference.
e.ra = currentMIPS->r[MIPS_REG_RA];
Core_Break("cpu.exception", address);
Core_Break(BreakReason::CpuException, address);
}

void Core_BreakException(u32 pc) {
Expand All @@ -583,7 +615,7 @@ void Core_BreakException(u32 pc) {
e.pc = pc;

if (!g_Config.bIgnoreBadMemAccess) {
Core_Break("cpu.breakInstruction", currentMIPS->pc);
Core_Break(BreakReason::BreakInstruction, currentMIPS->pc);
}
}

Expand Down
35 changes: 32 additions & 3 deletions Core/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,42 @@ enum class CPUStepType {
Frame,
};

// Must be set when breaking.
enum class BreakReason {
None,
DebugBreak,
DebugStep,
DebugStepInto,
UIFocus,
AfterFrame,
MemoryException,
CpuException,
BreakInstruction,
SavestateLoad,
SavestateSave,
SavestateRewind,
SavestateCrash,
MemoryBreakpoint,
CpuBreakpoint,
BreakpointUpdate,
MemoryAccess, // ???
JitBranchDebug,
BreakOnBoot,
RABreak,
AddBreakpoint,
FrameAdvance,
UIPause,
HLEDebugBreak,
};
const char *BreakReasonToString(BreakReason reason);

// Async, called from gui
void Core_Break(const char *reason, u32 relatedAddress = 0);
void Core_Break(BreakReason reason, u32 relatedAddress = 0);

// Resumes execution. Works both when stepping the CPU and the GE.
void Core_Resume();

const std::string &Core_BreakReason();
BreakReason Core_BreakReason();

// This should be called externally.
// Can fail if another step type was requested this frame.
Expand All @@ -62,7 +91,7 @@ void Core_SwitchToGe(); // Switches from CPU emulation to GE display list execu
// Changes every time we enter stepping.
int Core_GetSteppingCounter();
struct SteppingReason {
const char *reason = nullptr;
BreakReason reason;
u32 relatedAddress = 0;
};
SteppingReason Core_GetSteppingReason();
Expand Down
2 changes: 1 addition & 1 deletion Core/CoreTiming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ int RegisterEvent(const char *name, TimedCallback callback) {

void AntiCrashCallback(u64 userdata, int cyclesLate) {
ERROR_LOG(Log::SaveState, "Savestate broken: an unregistered event was called.");
Core_Break("savestate.crash", 0);
Core_Break(BreakReason::SavestateCrash, 0);
}

void RestoreRegisterEvent(int &event_type, const char *name, TimedCallback callback) {
Expand Down
6 changes: 3 additions & 3 deletions Core/Debugger/Breakpoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ BreakAction MemCheck::Action(u32 addr, bool write, int size, u32 pc, const char
// Conditions have always already been checked if we get here.
Log(addr, write, size, pc, reason);
if ((result & BREAK_ACTION_PAUSE) && coreState != CORE_POWERUP) {
Core_Break("memory.breakpoint", start);
Core_Break(BreakReason::MemoryBreakpoint, start);
}

return result;
Expand Down Expand Up @@ -316,7 +316,7 @@ BreakAction BreakpointManager::ExecBreakPoint(u32 addr) {
}
}
if ((info.result & BREAK_ACTION_PAUSE) && coreState != CORE_POWERUP) {
Core_Break("cpu.breakpoint", info.addr);
Core_Break(BreakReason::CpuBreakpoint, info.addr);
}

return info.result;
Expand Down Expand Up @@ -624,7 +624,7 @@ void BreakpointManager::Update(u32 addr) {
if (MIPSComp::jit && addr != -1) {
bool resume = false;
if (Core_IsStepping() == false) {
Core_Break("cpu.breakpoint.update", addr);
Core_Break(BreakReason::BreakpointUpdate, addr);
Core_WaitInactive();
resume = true;
}
Expand Down
2 changes: 1 addition & 1 deletion Core/Debugger/WebSocket/CPUCoreSubscriber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void WebSocketCPUStepping(DebuggerRequest &req) {
return req.Fail("CPU not started");
}
if (!Core_IsStepping() && Core_IsActive()) {
Core_Break("cpu.stepping", 0);
Core_Break(BreakReason::DebugStep, 0);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Core/Debugger/WebSocket/MemorySubscriber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static AutoDisabledReplacements LockMemoryAndCPU(uint32_t addr, bool keepReplace
if (Core_IsStepping()) {
result.wasStepping = true;
} else {
Core_Break("memory.access", addr);
Core_Break(BreakReason::MemoryAccess, addr);
Core_WaitInactive();
}

Expand Down
4 changes: 2 additions & 2 deletions Core/Debugger/WebSocket/SteppingBroadcaster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ struct CPUSteppingEvent {
j.writeUint("pc", currentMIPS->pc);
// A double ought to be good enough for a 156 day debug session.
j.writeFloat("ticks", CoreTiming::GetTicks());
if (reason_.reason) {
j.writeString("reason", reason_.reason);
if (reason_.reason != BreakReason::None) {
j.writeString("reason", BreakReasonToString(reason_.reason));
j.writeUint("relatedAddress", reason_.relatedAddress);
}
j.end();
Expand Down
2 changes: 1 addition & 1 deletion Core/Debugger/WebSocket/SteppingSubscriber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void WebSocketSteppingState::Into(DebuggerRequest &req) {
if (!currentDebugMIPS->isAlive())
return req.Fail("CPU not started");
if (!Core_IsStepping()) {
Core_Break("cpu.stepInto", 0);
Core_Break(BreakReason::DebugStepInto, 0);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/HLE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ static bool hleExecuteDebugBreak(const HLEFunction *func) {
}

INFO_LOG(Log::CPU, "Broke after syscall: %s", func->name);
Core_Break("hle.step", g_syscallPC);
Core_Break(BreakReason::HLEDebugBreak, g_syscallPC);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion Core/MIPS/MIPSTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ static void RunUntilWithChecks(u64 globalTicks) {
if (hasBPs && g_breakpoints.IsAddressBreakPoint(curMips->pc) && g_breakpoints.CheckSkipFirst() != curMips->pc) {
auto cond = g_breakpoints.GetBreakPointCondition(currentMIPS->pc);
if (!cond || cond->Evaluate()) {
Core_Break("cpu.breakpoint", curMips->pc);
Core_Break(BreakReason::CpuBreakpoint, curMips->pc);
if (g_breakpoints.IsTempBreakPoint(curMips->pc))
g_breakpoints.RemoveBreakPoint(curMips->pc);
break;
Expand Down
2 changes: 1 addition & 1 deletion Core/MIPS/x86/CompBranch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static void JitBranchLogMismatch(MIPSOpcode op, u32 pc)
char temp[256];
MIPSDisAsm(op, pc, temp, sizeof(temp), true);
ERROR_LOG(Log::JIT, "Bad jump: %s - int:%08x jit:%08x", temp, currentMIPS->intBranchExit, currentMIPS->jitBranchExit);
Core_Break("jit.branchdebug", pc);
Core_Break(BreakReason::JitBranchDebug, pc);
}

void Jit::BranchLog(MIPSOpcode op)
Expand Down
2 changes: 1 addition & 1 deletion Core/RetroAchievements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ static void raintegration_event_handler(const rc_client_raintegration_event_t *e
break;
case RC_CLIENT_RAINTEGRATION_EVENT_PAUSE:
// The toolkit has hit a breakpoint and wants to pause the emulator. Do so.
Core_Break("ra_breakpoint");
Core_Break(BreakReason::RABreak);
break;
case RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED:
// Hardcore mode has been changed (either directly by the user, or disabled through the use of the tools).
Expand Down
6 changes: 3 additions & 3 deletions Core/SaveState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ double g_lastSaveTime = -1.0;

rewindStates.NotifyState();
if (coreState == CoreState::CORE_RUNTIME_ERROR)
Core_Break("savestate.load", 0);
Core_Break(BreakReason::SavestateLoad, 0);
Enqueue(Operation(SAVESTATE_LOAD, filename, slot, callback, cbUserData));
}

Expand All @@ -444,7 +444,7 @@ double g_lastSaveTime = -1.0;

rewindStates.NotifyState();
if (coreState == CoreState::CORE_RUNTIME_ERROR)
Core_Break("savestate.save", 0);
Core_Break(BreakReason::SavestateSave, 0);
Enqueue(Operation(SAVESTATE_SAVE, filename, slot, callback, cbUserData));
}

Expand All @@ -459,7 +459,7 @@ double g_lastSaveTime = -1.0;
return;
}
if (coreState == CoreState::CORE_RUNTIME_ERROR)
Core_Break("savestate.rewind", 0);
Core_Break(BreakReason::SavestateRewind, 0);
Enqueue(Operation(SAVESTATE_REWIND, Path(), -1, callback, cbUserData));
}

Expand Down
2 changes: 1 addition & 1 deletion SDL/CocoaBarItems.mm
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ -(void)breakAction: (NSMenuItem *)item {
Core_Resume();
item.title = DESKTOPUI_LOCALIZED("Break");
} else {
Core_Break("ui.break", 0);
Core_Break(BreakReason::DebugBreak, 0);
item.title = DEVELOPERUI_LOCALIZED("Resume");
}
}
Expand Down
11 changes: 5 additions & 6 deletions UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,9 @@ static void __EmuScreenVblank()
{
auto sy = GetI18NCategory(I18NCat::SYSTEM);

if (frameStep_ && lastNumFlips != gpuStats.numFlips)
{
if (frameStep_ && lastNumFlips != gpuStats.numFlips) {
frameStep_ = false;
Core_Break("ui.frameAdvance", 0);
Core_Break(BreakReason::FrameAdvance, 0);
lastNumFlips = gpuStats.numFlips;
}
#ifndef MOBILE_DEVICE
Expand Down Expand Up @@ -772,10 +771,10 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
case VIRTKEY_PAUSE_NO_MENU:
if (down && !NetworkWarnUserIfOnlineAndCantSpeed()) {
// We re-use debug break/resume to implement pause/resume without a menu.
if (coreState == CORE_STEPPING_CPU) {
if (coreState == CORE_STEPPING_CPU) { // should we check reason?
Core_Resume();
} else {
Core_Break("user-pause");
Core_Break(BreakReason::UIPause);
}
}
break;
Expand Down Expand Up @@ -1586,7 +1585,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
Core_Resume();
} else if (!frameStep_) {
lastNumFlips = gpuStats.numFlips;
Core_Break("ui.frameAdvance", 0);
Core_Break(BreakReason::FrameAdvance, 0);
}
}
}
Expand Down
Loading
Loading