summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp57
-rw-r--r--src/core/core.h16
-rw-r--r--src/core/core_cpu.cpp72
-rw-r--r--src/core/core_cpu.h46
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