Merge pull request #5180 from lioncash/enum

CPU: Convert state enum to an enum class
This commit is contained in:
Markus Wick 2017-04-02 17:01:25 +02:00 committed by GitHub
commit 40cfa708a8
17 changed files with 68 additions and 56 deletions

View File

@ -352,7 +352,7 @@ static void CpuThread()
if (!s_state_filename.empty())
{
// Needs to PauseAndLock the Core
// NOTE: EmuThread should have left us in CPU_STEPPING so nothing will happen
// NOTE: EmuThread should have left us in State::Stepping so nothing will happen
// until after the job is serviced.
QueueHostJob([] {
// Recheck in case Movie cleared it since.
@ -431,11 +431,11 @@ static void FifoPlayerThread()
// If we did not enter the CPU Run Loop above then run a fake one instead.
// We need to be IsRunningAndStarted() for DolphinWX to stop us.
if (CPU::GetState() != CPU::CPU_POWERDOWN)
if (CPU::GetState() != CPU::State::PowerDown)
{
s_is_started = true;
Host_Message(WM_USER_STOP);
while (CPU::GetState() != CPU::CPU_POWERDOWN)
while (CPU::GetState() != CPU::State::PowerDown)
{
if (!_CoreParameter.bCPUThread)
g_video_backend->PeekMessages();
@ -594,7 +594,7 @@ void EmuThread()
// Spawn the CPU+GPU thread
s_cpu_thread = std::thread(cpuThreadFunc);
while (CPU::GetState() != CPU::CPU_POWERDOWN)
while (CPU::GetState() != CPU::State::PowerDown)
{
g_video_backend->PeekMessages();
Common::SleepCurrentThread(20);

View File

@ -99,19 +99,22 @@ public:
const char* GetName() override { return "FifoPlayer"; }
void Run() override
{
while (CPU::GetState() == CPU::CPU_RUNNING)
while (CPU::GetState() == CPU::State::Running)
{
switch (m_parent->AdvanceFrame())
{
case CPU::CPU_POWERDOWN:
case CPU::State::PowerDown:
CPU::Break();
Host_Message(WM_USER_STOP);
break;
case CPU::CPU_STEPPING:
case CPU::State::Stepping:
CPU::Break();
Host_UpdateMainFrame();
break;
case CPU::State::Running:
break;
}
}
}
@ -120,15 +123,15 @@ private:
FifoPlayer* m_parent;
};
int FifoPlayer::AdvanceFrame()
CPU::State FifoPlayer::AdvanceFrame()
{
if (m_CurrentFrame >= m_FrameRangeEnd)
{
if (!m_Loop)
return CPU::CPU_POWERDOWN;
return CPU::State::PowerDown;
// If there are zero frames in the range then sleep instead of busy spinning
if (m_FrameRangeStart >= m_FrameRangeEnd)
return CPU::CPU_STEPPING;
return CPU::State::Stepping;
// When looping, reload the contents of all the BP/CP/CF registers.
// This ensures that each time the first frame is played back, the state of the
@ -148,7 +151,7 @@ int FifoPlayer::AdvanceFrame()
WriteFrame(m_File->GetFrame(m_CurrentFrame), m_FrameInfo[m_CurrentFrame]);
++m_CurrentFrame;
return CPU::CPU_RUNNING;
return CPU::State::Running;
}
std::unique_ptr<CPUCoreBase> FifoPlayer::GetCPUCore()

View File

@ -16,6 +16,11 @@ class FifoDataFile;
struct MemoryUpdate;
struct AnalyzedFrameInfo;
namespace CPU
{
enum class State;
}
// Story time:
// When FifoRecorder was created, efb copies weren't really used or they used efb2tex which ignored
// the underlying memory, so FifoRecorder didn't do anything special about the memory backing efb
@ -94,7 +99,7 @@ private:
FifoPlayer();
int AdvanceFrame();
CPU::State AdvanceFrame();
void WriteFrame(const FifoFrameInfo& frame, const AnalyzedFrameInfo& info);
void WriteFramePart(u32 dataStart, u32 dataEnd, u32& nextMemUpdate, const FifoFrameInfo& frame,

View File

@ -22,7 +22,7 @@ namespace CPU
// CPU Thread execution state.
// Requires s_state_change_lock to modify the value.
// Read access is unsynchronized.
static State s_state = CPU_POWERDOWN;
static State s_state = State::PowerDown;
// Synchronizes EnableStepping and PauseAndLock so only one instance can be
// active at a time. Simplifies code by eliminating several edge cases where
@ -50,7 +50,7 @@ static Common::Event* s_state_cpu_step_instruction_sync = nullptr;
void Init(int cpu_core)
{
PowerPC::Init(cpu_core);
s_state = CPU_STEPPING;
s_state = State::Stepping;
}
void Shutdown()
@ -73,13 +73,13 @@ static void FlushStepSyncEventLocked()
void Run()
{
std::unique_lock<std::mutex> state_lock(s_state_change_lock);
while (s_state != CPU_POWERDOWN)
while (s_state != State::PowerDown)
{
s_state_cpu_cvar.wait(state_lock, [] { return !s_state_paused_and_locked; });
switch (s_state)
{
case CPU_RUNNING:
case State::Running:
s_state_cpu_thread_active = true;
state_lock.unlock();
@ -91,12 +91,12 @@ void Run()
{
if (PowerPC::breakpoints.IsAddressBreakPoint(PC) || PowerPC::memchecks.HasAny())
{
s_state = CPU_STEPPING;
s_state = State::Stepping;
PowerPC::CoreMode old_mode = PowerPC::GetMode();
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
PowerPC::SingleStep();
PowerPC::SetMode(old_mode);
s_state = CPU_RUNNING;
s_state = State::Running;
}
}
@ -108,11 +108,11 @@ void Run()
s_state_cpu_idle_cvar.notify_all();
break;
case CPU_STEPPING:
case State::Stepping:
// Wait for step command.
s_state_cpu_cvar.wait(state_lock,
[] { return s_state_cpu_step_instruction || s_state != CPU_STEPPING; });
if (s_state != CPU_STEPPING)
[] { return s_state_cpu_step_instruction || !IsStepping(); });
if (!IsStepping())
{
// Signal event if the mode changes.
FlushStepSyncEventLocked();
@ -136,7 +136,7 @@ void Run()
Host_UpdateDisasmDialog();
break;
case CPU_POWERDOWN:
case State::PowerDown:
break;
}
}
@ -155,10 +155,10 @@ static void RunAdjacentSystems(bool running)
void Stop()
{
// Change state and wait for it to be acknowledged.
// We don't need the stepping lock because CPU_POWERDOWN is a priority state which
// We don't need the stepping lock because State::PowerDown is a priority state which
// will stick permanently.
std::unique_lock<std::mutex> state_lock(s_state_change_lock);
s_state = CPU_POWERDOWN;
s_state = State::PowerDown;
s_state_cpu_cvar.notify_one();
while (s_state_cpu_thread_active)
@ -175,7 +175,7 @@ void Stop()
bool IsStepping()
{
return s_state == CPU_STEPPING;
return s_state == State::Stepping;
}
State GetState()
@ -215,7 +215,7 @@ void StepOpcode(Common::Event* event)
// Requires s_state_change_lock
static bool SetStateLocked(State s)
{
if (s_state == CPU_POWERDOWN)
if (s_state == State::PowerDown)
return false;
s_state = s;
return true;
@ -228,7 +228,7 @@ void EnableStepping(bool stepping)
if (stepping)
{
SetStateLocked(CPU_STEPPING);
SetStateLocked(State::Stepping);
while (s_state_cpu_thread_active)
{
@ -240,7 +240,7 @@ void EnableStepping(bool stepping)
RunAdjacentSystems(false);
}
else if (SetStateLocked(CPU_RUNNING))
else if (SetStateLocked(State::Running))
{
s_state_cpu_cvar.notify_one();
RunAdjacentSystems(true);
@ -261,7 +261,7 @@ void Break()
// We'll deadlock if we synchronize, the CPU may block waiting for our caller to
// finish resulting in the CPU loop never terminating.
SetStateLocked(CPU_STEPPING);
SetStateLocked(State::Stepping);
RunAdjacentSystems(false);
}
@ -278,8 +278,8 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
std::unique_lock<std::mutex> state_lock(s_state_change_lock);
s_state_paused_and_locked = true;
was_unpaused = s_state == CPU_RUNNING;
SetStateLocked(CPU_STEPPING);
was_unpaused = s_state == State::Running;
SetStateLocked(State::Stepping);
while (s_state_cpu_thread_active)
{
@ -316,7 +316,7 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
{
s_state_system_request_stepping = false;
}
else if (unpause_on_unlock && SetStateLocked(CPU_RUNNING))
else if (unpause_on_unlock && SetStateLocked(State::Running))
{
was_unpaused = true;
}
@ -324,7 +324,7 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
s_state_cpu_cvar.notify_one();
if (control_adjacent)
RunAdjacentSystems(s_state == CPU_RUNNING);
RunAdjacentSystems(s_state == State::Running);
}
s_stepping_lock.unlock();
}

View File

@ -11,11 +11,11 @@ class Event;
namespace CPU
{
enum State
enum class State
{
CPU_RUNNING = 0,
CPU_STEPPING = 2,
CPU_POWERDOWN = 3
Running = 0,
Stepping = 2,
PowerDown = 3
};
// Init
@ -29,7 +29,7 @@ void Shutdown();
void Run();
// Causes shutdown
// Once started, CPU_POWERDOWN cannot be stopped.
// Once started, State::PowerDown cannot be stopped.
// Synchronizes with the CPU Thread (waits for CPU::Run to exit).
void Stop();
@ -48,8 +48,8 @@ void EnableStepping(bool stepping);
// should not be used by the Host.
void Break();
// Shorthand for GetState() == CPU_STEPPING.
// WARNING: CPU_POWERDOWN will return false, not just CPU_RUNNING.
// Shorthand for GetState() == State::Stepping.
// WARNING: State::PowerDown will return false, not just State::Running.
bool IsStepping();
// Get current CPU Thread State
@ -63,8 +63,8 @@ const volatile State* GetStatePtr();
// While this lock is held, the CPU Thread will not perform any action so it is safe to access
// PowerPC::ppcState, CoreTiming, etc. without racing the CPU Thread.
// Cannot be used recursively. Must be paired as PauseAndLock(true)/PauseAndLock(false).
// Return value for do_lock == true is whether the state was CPU_RUNNING or not.
// Return value for do_lock == false is whether the state was changed *to* CPU_RUNNING or not.
// Return value for do_lock == true is whether the state was State::Running or not.
// Return value for do_lock == false is whether the state was changed *to* State::Running or not.
// Cannot be used by System threads as it will deadlock. It is threadsafe otherwise.
// "control_adjacent" causes PauseAndLock to behave like EnableStepping by modifying the
// state of the Audio and FIFO subsystems as well.

View File

@ -1344,7 +1344,7 @@ void EndPlayInput(bool cont)
}
else if (s_playMode != MODE_NONE)
{
// We can be called by EmuThread during boot (CPU_POWERDOWN)
// We can be called by EmuThread during boot (CPU::State::PowerDown)
bool was_running = Core::IsRunningAndStarted() && !CPU::IsStepping();
if (was_running)
CPU::Break();

View File

@ -107,7 +107,7 @@ void CachedInterpreter::ExecuteOneBlock()
void CachedInterpreter::Run()
{
while (CPU::GetState() == CPU::CPU_RUNNING)
while (CPU::GetState() == CPU::State::Running)
{
// Start new timing slice
// NOTE: Exceptions may change PC

View File

@ -224,7 +224,7 @@ int ShowSteps = 300;
// FastRun - inspired by GCemu (to imitate the JIT so that they can be compared).
void Interpreter::Run()
{
while (!CPU::GetState())
while (CPU::GetState() == CPU::State::Running)
{
// CoreTiming Advance() ends the previous slice and declares the start of the next
// one so it must always be called at the start. At boot, we are in slice -1 and must

View File

@ -583,7 +583,7 @@ void Jit64::Jit(u32 em_address)
// Comment out the following to disable breakpoints (speed-up)
if (!Profiler::g_ProfileBlocks)
{
if (CPU::GetState() == CPU::CPU_STEPPING)
if (CPU::IsStepping())
{
blockSize = 1;
@ -841,7 +841,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc
}
if (SConfig::GetInstance().bEnableDebugging &&
breakpoints.IsAddressBreakPoint(ops[i].address) && CPU::GetState() != CPU::CPU_STEPPING)
breakpoints.IsAddressBreakPoint(ops[i].address) && !CPU::IsStepping())
{
// Turn off block linking if there are breakpoints so that the Step Over command does not
// link this block.

View File

@ -84,7 +84,7 @@ void Jit64AsmRoutineManager::Generate()
if (SConfig::GetInstance().bEnableDebugging)
{
TEST(32, M(CPU::GetStatePtr()), Imm32(CPU::CPU_STEPPING));
TEST(32, M(CPU::GetStatePtr()), Imm32(static_cast<u32>(CPU::State::Stepping)));
FixupBranch notStepping = J_CC(CC_Z);
ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunction(PowerPC::CheckBreakPoints);

View File

@ -119,7 +119,7 @@ void Jit64::lXXx(UGeckoInstruction inst)
signExtend = true;
}
if (CPU::GetState() != CPU::CPU_STEPPING && inst.OPCD == 32 && CanMergeNextInstructions(2) &&
if (!CPU::IsStepping() && inst.OPCD == 32 && CanMergeNextInstructions(2) &&
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
(js.op[1].inst.hex == 0x28000000 ||
(SConfig::GetInstance().bWii && js.op[1].inst.hex == 0x2C000000)) &&

View File

@ -487,7 +487,7 @@ void JitIL::Jit(u32 em_address)
// Comment out the following to disable breakpoints (speed-up)
if (!Profiler::g_ProfileBlocks)
{
if (CPU::GetState() == CPU::CPU_STEPPING)
if (CPU::IsStepping())
{
blockSize = 1;
@ -638,7 +638,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc
}
if (SConfig::GetInstance().bEnableDebugging &&
breakpoints.IsAddressBreakPoint(ops[i].address) && CPU::GetState() != CPU::CPU_STEPPING)
breakpoints.IsAddressBreakPoint(ops[i].address) && !CPU::IsStepping())
{
// Turn off block linking if there are breakpoints so that the Step Over command does not
// link this block.

View File

@ -66,7 +66,7 @@ void JitArm64::GenerateAsm()
// } while (PowerPC::ppcState.downcount > 0);
// doTiming:
// NPC = PC = DISPATCHER_PC;
// } while (CPU::GetState() == CPU::CPU_RUNNING);
// } while (CPU::GetState() == CPU::State::Running);
AlignCodePage();
dispatcher = GetCodePtr();
WARN_LOG(DYNA_REC, "Dispatcher is %p", dispatcher);

View File

@ -29,7 +29,7 @@ JitBase::~JitBase() = default;
bool JitBase::CanMergeNextInstructions(int count) const
{
if (CPU::GetState() == CPU::CPU_STEPPING || js.instructionsLeft < count)
if (CPU::IsStepping() || js.instructionsLeft < count)
return false;
// Be careful: a breakpoint kills flags in between instructions
for (int i = 1; i <= count; i++)

View File

@ -57,7 +57,7 @@ void JitILBase::lXz(UGeckoInstruction inst)
// TODO: This really should be done somewhere else. Either lower in the IR
// or higher in PPCAnalyst
// TODO: We shouldn't use debug reads here.
if (CPU::GetState() != CPU::CPU_STEPPING && inst.OPCD == 32 && // Lwx
if (!CPU::IsStepping() && inst.OPCD == 32 && // Lwx
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
(PowerPC::HostRead_U32(js.compilerPC + 4) == 0x28000000 ||
(SConfig::GetInstance().bWii && PowerPC::HostRead_U32(js.compilerPC + 4) == 0x2C000000)) &&

View File

@ -210,11 +210,15 @@ void Reset()
void ScheduleInvalidateCacheThreadSafe(u32 address)
{
if (CPU::GetState() == CPU::State::CPU_RUNNING)
if (CPU::GetState() == CPU::State::Running)
{
CoreTiming::ScheduleEvent(0, s_invalidate_cache_thread_safe, address,
CoreTiming::FromThread::NON_CPU);
}
else
{
PowerPC::ppcState.iCache.Invalidate(static_cast<u32>(address));
}
}
void Shutdown()

View File

@ -152,7 +152,7 @@ const char* GetCPUName();
// Init() will be called when added and Shutdown() when removed.
// [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU
// run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself
// while it is CPU_RUNNING]
// while it is in State::Running]
void InjectExternalCPUCore(CPUCoreBase* core);
// Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread)