diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/core.cpp | 57 | ||||
-rw-r--r-- | src/core/core.h | 16 | ||||
-rw-r--r-- | src/core/core_cpu.cpp | 72 | ||||
-rw-r--r-- | src/core/core_cpu.h | 46 |
5 files changed, 135 insertions, 58 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a41e22f4a..821d2f883 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -4,6 +4,8 @@ add_library(core STATIC arm/unicorn/arm_unicorn.h core.cpp core.h + core_cpu.cpp + core_cpu.h core_timing.cpp core_timing.h file_sys/directory.h diff --git a/src/core/core.cpp b/src/core/core.cpp index 9e2229d02..0af78c18c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -5,10 +5,6 @@ #include <memory> #include <utility> #include "common/logging/log.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" -#endif -#include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" #include "core/core_timing.h" #include "core/gdbstub/gdbstub.h" @@ -33,9 +29,6 @@ System::~System() = default; System::ResultStatus System::RunLoop(bool tight_loop) { status = ResultStatus::Success; - if (!cpu_core) { - return ResultStatus::ErrorNotInitialized; - } if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -52,24 +45,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } } - // If we don't have a currently active thread then don't execute instructions, - // instead advance to the next event and try to yield to the next thread - if (Kernel::GetCurrentThread() == nullptr) { - NGLOG_TRACE(Core_ARM, "Idling"); - CoreTiming::Idle(); - CoreTiming::Advance(); - PrepareReschedule(); - } else { - CoreTiming::Advance(); - if (tight_loop) { - cpu_core->Run(); - } else { - cpu_core->Step(); - } - } - - HW::Update(); - Reschedule(); + cpu_cores[0]->RunLoop(tight_loop); return status; } @@ -133,23 +109,13 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file } void System::PrepareReschedule() { - cpu_core->PrepareReschedule(); - reschedule_pending = true; + cpu_cores[0]->PrepareReschedule(); } PerfStats::Results System::GetAndResetPerfStats() { return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); } -void System::Reschedule() { - if (!reschedule_pending) { - return; - } - - reschedule_pending = false; - Core::System::GetInstance().Scheduler().Reschedule(); -} - System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { NGLOG_DEBUG(HW_Memory, "initialized OK"); @@ -157,15 +123,8 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { current_process = Kernel::Process::Create("main"); - if (Settings::values.use_cpu_jit) { -#ifdef ARCHITECTURE_x86_64 - cpu_core = std::make_shared<ARM_Dynarmic>(); -#else - cpu_core = std::make_shared<ARM_Unicorn>(); - NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); -#endif - } else { - cpu_core = std::make_shared<ARM_Unicorn>(); + for (auto& cpu_core : cpu_cores) { + cpu_core = std::make_unique<Cpu>(); } gpu_core = std::make_unique<Tegra::GPU>(); @@ -176,7 +135,6 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { HW::Init(); Kernel::Init(system_mode); - scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get()); Service::Init(service_manager); GDBStub::Init(); @@ -207,13 +165,16 @@ void System::Shutdown() { VideoCore::Shutdown(); GDBStub::Shutdown(); Service::Shutdown(); - scheduler.reset(); Kernel::Shutdown(); HW::Shutdown(); service_manager.reset(); telemetry_session.reset(); gpu_core.reset(); - cpu_core.reset(); + + for (auto& cpu_core : cpu_cores) { + cpu_core.reset(); + } + CoreTiming::Shutdown(); app_loader.reset(); diff --git a/src/core/core.h b/src/core/core.h index f81cbfb3c..6e6cc7579 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -4,9 +4,11 @@ #pragma once +#include <array> #include <memory> #include <string> #include "common/common_types.h" +#include "core/core_cpu.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/scheduler.h" #include "core/loader/loader.h" @@ -89,7 +91,7 @@ public: * @returns True if the emulated system is powered on, otherwise false. */ bool IsPoweredOn() const { - return cpu_core != nullptr; + return cpu_cores[0] != nullptr; } /** @@ -110,7 +112,7 @@ public: * @returns A reference to the emulated CPU. */ ARM_Interface& CPU() { - return *cpu_core; + return cpu_cores[0]->CPU(); } Tegra::GPU& GPU() { @@ -118,7 +120,7 @@ public: } Kernel::Scheduler& Scheduler() { - return *scheduler; + return cpu_cores[0]->Scheduler(); } Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { @@ -163,18 +165,12 @@ private: */ ResultStatus Init(EmuWindow* emu_window, u32 system_mode); - /// Reschedule the core emulation - void Reschedule(); - /// AppLoader used to load the current executing application std::unique_ptr<Loader::AppLoader> app_loader; - std::shared_ptr<ARM_Interface> cpu_core; - std::unique_ptr<Kernel::Scheduler> scheduler; + std::array<std::unique_ptr<Cpu>, 4> cpu_cores; std::unique_ptr<Tegra::GPU> gpu_core; - std::shared_ptr<Tegra::DebugContext> debug_context; - Kernel::SharedPtr<Kernel::Process> current_process; /// When true, signals that a reschedule should happen diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp new file mode 100644 index 000000000..81c0e212d --- /dev/null +++ b/src/core/core_cpu.cpp @@ -0,0 +1,72 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif +#include "core/arm/unicorn/arm_unicorn.h" +#include "core/core_cpu.h" +#include "core/core_timing.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/thread.h" +#include "core/settings.h" + +namespace Core { + +Cpu::Cpu() { + if (Settings::values.use_cpu_jit) { +#ifdef ARCHITECTURE_x86_64 + arm_interface = std::make_shared<ARM_Dynarmic>(); +#else + cpu_core = std::make_shared<ARM_Unicorn>(); + NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); +#endif + } else { + arm_interface = std::make_shared<ARM_Unicorn>(); + } + + scheduler = std::make_unique<Kernel::Scheduler>(arm_interface.get()); +} + +void Cpu::RunLoop(bool tight_loop) { + // If we don't have a currently active thread then don't execute instructions, + // instead advance to the next event and try to yield to the next thread + if (Kernel::GetCurrentThread() == nullptr) { + NGLOG_TRACE(Core, "Idling"); + CoreTiming::Idle(); + CoreTiming::Advance(); + PrepareReschedule(); + } else { + CoreTiming::Advance(); + if (tight_loop) { + arm_interface->Run(); + } else { + arm_interface->Step(); + } + } + + Reschedule(); +} + +void Cpu::SingleStep() { + return RunLoop(false); +} + +void Cpu::PrepareReschedule() { + arm_interface->PrepareReschedule(); + reschedule_pending = true; +} + +void Cpu::Reschedule() { + if (!reschedule_pending) { + return; + } + + reschedule_pending = false; + scheduler->Reschedule(); +} + +} // namespace Core diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h new file mode 100644 index 000000000..312db1655 --- /dev/null +++ b/src/core/core_cpu.h @@ -0,0 +1,46 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include "common/common_types.h" + +class ARM_Interface; + +namespace Kernel { +class Scheduler; +} + +namespace Core { + +class Cpu { +public: + Cpu(); + + void RunLoop(bool tight_loop = true); + + void SingleStep(); + + void PrepareReschedule(); + + ARM_Interface& CPU() { + return *arm_interface; + } + + Kernel::Scheduler& Scheduler() { + return *scheduler; + } + +private: + void Reschedule(); + + std::shared_ptr<ARM_Interface> arm_interface; + std::unique_ptr<Kernel::Scheduler> scheduler; + + bool reschedule_pending{}; +}; + +} // namespace Core |