summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-05-01 22:21:38 -0400
committerGravatar bunnei2018-05-10 19:34:46 -0400
commit559024593086d04e24a99a9f77490a3f97cf952d (patch)
tree0b9163a33ae973bd69cb3883bea1e91a3581f527 /src
parentStubs for QLaunch (#428) (diff)
downloadyuzu-559024593086d04e24a99a9f77490a3f97cf952d.tar.gz
yuzu-559024593086d04e24a99a9f77490a3f97cf952d.tar.xz
yuzu-559024593086d04e24a99a9f77490a3f97cf952d.zip
core: Move common CPU core things to its own class.
Diffstat (limited to 'src')
-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
4 arm/unicorn/arm_unicorn.h 4 arm/unicorn/arm_unicorn.h
5 core.cpp 5 core.cpp
6 core.h 6 core.h
7 core_cpu.cpp
8 core_cpu.h
7 core_timing.cpp 9 core_timing.cpp
8 core_timing.h 10 core_timing.h
9 file_sys/directory.h 11 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 @@
5#include <memory> 5#include <memory>
6#include <utility> 6#include <utility>
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#ifdef ARCHITECTURE_x86_64
9#include "core/arm/dynarmic/arm_dynarmic.h"
10#endif
11#include "core/arm/unicorn/arm_unicorn.h"
12#include "core/core.h" 8#include "core/core.h"
13#include "core/core_timing.h" 9#include "core/core_timing.h"
14#include "core/gdbstub/gdbstub.h" 10#include "core/gdbstub/gdbstub.h"
@@ -33,9 +29,6 @@ System::~System() = default;
33 29
34System::ResultStatus System::RunLoop(bool tight_loop) { 30System::ResultStatus System::RunLoop(bool tight_loop) {
35 status = ResultStatus::Success; 31 status = ResultStatus::Success;
36 if (!cpu_core) {
37 return ResultStatus::ErrorNotInitialized;
38 }
39 32
40 if (GDBStub::IsServerEnabled()) { 33 if (GDBStub::IsServerEnabled()) {
41 GDBStub::HandlePacket(); 34 GDBStub::HandlePacket();
@@ -52,24 +45,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
52 } 45 }
53 } 46 }
54 47
55 // If we don't have a currently active thread then don't execute instructions, 48 cpu_cores[0]->RunLoop(tight_loop);
56 // instead advance to the next event and try to yield to the next thread
57 if (Kernel::GetCurrentThread() == nullptr) {
58 NGLOG_TRACE(Core_ARM, "Idling");
59 CoreTiming::Idle();
60 CoreTiming::Advance();
61 PrepareReschedule();
62 } else {
63 CoreTiming::Advance();
64 if (tight_loop) {
65 cpu_core->Run();
66 } else {
67 cpu_core->Step();
68 }
69 }
70
71 HW::Update();
72 Reschedule();
73 49
74 return status; 50 return status;
75} 51}
@@ -133,23 +109,13 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
133} 109}
134 110
135void System::PrepareReschedule() { 111void System::PrepareReschedule() {
136 cpu_core->PrepareReschedule(); 112 cpu_cores[0]->PrepareReschedule();
137 reschedule_pending = true;
138} 113}
139 114
140PerfStats::Results System::GetAndResetPerfStats() { 115PerfStats::Results System::GetAndResetPerfStats() {
141 return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); 116 return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
142} 117}
143 118
144void System::Reschedule() {
145 if (!reschedule_pending) {
146 return;
147 }
148
149 reschedule_pending = false;
150 Core::System::GetInstance().Scheduler().Reschedule();
151}
152
153System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { 119System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
154 NGLOG_DEBUG(HW_Memory, "initialized OK"); 120 NGLOG_DEBUG(HW_Memory, "initialized OK");
155 121
@@ -157,15 +123,8 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
157 123
158 current_process = Kernel::Process::Create("main"); 124 current_process = Kernel::Process::Create("main");
159 125
160 if (Settings::values.use_cpu_jit) { 126 for (auto& cpu_core : cpu_cores) {
161#ifdef ARCHITECTURE_x86_64 127 cpu_core = std::make_unique<Cpu>();
162 cpu_core = std::make_shared<ARM_Dynarmic>();
163#else
164 cpu_core = std::make_shared<ARM_Unicorn>();
165 NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
166#endif
167 } else {
168 cpu_core = std::make_shared<ARM_Unicorn>();
169 } 128 }
170 129
171 gpu_core = std::make_unique<Tegra::GPU>(); 130 gpu_core = std::make_unique<Tegra::GPU>();
@@ -176,7 +135,6 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
176 135
177 HW::Init(); 136 HW::Init();
178 Kernel::Init(system_mode); 137 Kernel::Init(system_mode);
179 scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get());
180 Service::Init(service_manager); 138 Service::Init(service_manager);
181 GDBStub::Init(); 139 GDBStub::Init();
182 140
@@ -207,13 +165,16 @@ void System::Shutdown() {
207 VideoCore::Shutdown(); 165 VideoCore::Shutdown();
208 GDBStub::Shutdown(); 166 GDBStub::Shutdown();
209 Service::Shutdown(); 167 Service::Shutdown();
210 scheduler.reset();
211 Kernel::Shutdown(); 168 Kernel::Shutdown();
212 HW::Shutdown(); 169 HW::Shutdown();
213 service_manager.reset(); 170 service_manager.reset();
214 telemetry_session.reset(); 171 telemetry_session.reset();
215 gpu_core.reset(); 172 gpu_core.reset();
216 cpu_core.reset(); 173
174 for (auto& cpu_core : cpu_cores) {
175 cpu_core.reset();
176 }
177
217 CoreTiming::Shutdown(); 178 CoreTiming::Shutdown();
218 179
219 app_loader.reset(); 180 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <memory> 8#include <memory>
8#include <string> 9#include <string>
9#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/core_cpu.h"
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/scheduler.h" 13#include "core/hle/kernel/scheduler.h"
12#include "core/loader/loader.h" 14#include "core/loader/loader.h"
@@ -89,7 +91,7 @@ public:
89 * @returns True if the emulated system is powered on, otherwise false. 91 * @returns True if the emulated system is powered on, otherwise false.
90 */ 92 */
91 bool IsPoweredOn() const { 93 bool IsPoweredOn() const {
92 return cpu_core != nullptr; 94 return cpu_cores[0] != nullptr;
93 } 95 }
94 96
95 /** 97 /**
@@ -110,7 +112,7 @@ public:
110 * @returns A reference to the emulated CPU. 112 * @returns A reference to the emulated CPU.
111 */ 113 */
112 ARM_Interface& CPU() { 114 ARM_Interface& CPU() {
113 return *cpu_core; 115 return cpu_cores[0]->CPU();
114 } 116 }
115 117
116 Tegra::GPU& GPU() { 118 Tegra::GPU& GPU() {
@@ -118,7 +120,7 @@ public:
118 } 120 }
119 121
120 Kernel::Scheduler& Scheduler() { 122 Kernel::Scheduler& Scheduler() {
121 return *scheduler; 123 return cpu_cores[0]->Scheduler();
122 } 124 }
123 125
124 Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { 126 Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
@@ -163,18 +165,12 @@ private:
163 */ 165 */
164 ResultStatus Init(EmuWindow* emu_window, u32 system_mode); 166 ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
165 167
166 /// Reschedule the core emulation
167 void Reschedule();
168
169 /// AppLoader used to load the current executing application 168 /// AppLoader used to load the current executing application
170 std::unique_ptr<Loader::AppLoader> app_loader; 169 std::unique_ptr<Loader::AppLoader> app_loader;
171 170
172 std::shared_ptr<ARM_Interface> cpu_core; 171 std::array<std::unique_ptr<Cpu>, 4> cpu_cores;
173 std::unique_ptr<Kernel::Scheduler> scheduler;
174 std::unique_ptr<Tegra::GPU> gpu_core; 172 std::unique_ptr<Tegra::GPU> gpu_core;
175
176 std::shared_ptr<Tegra::DebugContext> debug_context; 173 std::shared_ptr<Tegra::DebugContext> debug_context;
177
178 Kernel::SharedPtr<Kernel::Process> current_process; 174 Kernel::SharedPtr<Kernel::Process> current_process;
179 175
180 /// When true, signals that a reschedule should happen 176 /// 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 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#ifdef ARCHITECTURE_x86_64
7#include "core/arm/dynarmic/arm_dynarmic.h"
8#endif
9#include "core/arm/unicorn/arm_unicorn.h"
10#include "core/core_cpu.h"
11#include "core/core_timing.h"
12#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/scheduler.h"
14#include "core/hle/kernel/thread.h"
15#include "core/settings.h"
16
17namespace Core {
18
19Cpu::Cpu() {
20 if (Settings::values.use_cpu_jit) {
21#ifdef ARCHITECTURE_x86_64
22 arm_interface = std::make_shared<ARM_Dynarmic>();
23#else
24 cpu_core = std::make_shared<ARM_Unicorn>();
25 NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
26#endif
27 } else {
28 arm_interface = std::make_shared<ARM_Unicorn>();
29 }
30
31 scheduler = std::make_unique<Kernel::Scheduler>(arm_interface.get());
32}
33
34void Cpu::RunLoop(bool tight_loop) {
35 // If we don't have a currently active thread then don't execute instructions,
36 // instead advance to the next event and try to yield to the next thread
37 if (Kernel::GetCurrentThread() == nullptr) {
38 NGLOG_TRACE(Core, "Idling");
39 CoreTiming::Idle();
40 CoreTiming::Advance();
41 PrepareReschedule();
42 } else {
43 CoreTiming::Advance();
44 if (tight_loop) {
45 arm_interface->Run();
46 } else {
47 arm_interface->Step();
48 }
49 }
50
51 Reschedule();
52}
53
54void Cpu::SingleStep() {
55 return RunLoop(false);
56}
57
58void Cpu::PrepareReschedule() {
59 arm_interface->PrepareReschedule();
60 reschedule_pending = true;
61}
62
63void Cpu::Reschedule() {
64 if (!reschedule_pending) {
65 return;
66 }
67
68 reschedule_pending = false;
69 scheduler->Reschedule();
70}
71
72} // 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 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <string>
9#include "common/common_types.h"
10
11class ARM_Interface;
12
13namespace Kernel {
14class Scheduler;
15}
16
17namespace Core {
18
19class Cpu {
20public:
21 Cpu();
22
23 void RunLoop(bool tight_loop = true);
24
25 void SingleStep();
26
27 void PrepareReschedule();
28
29 ARM_Interface& CPU() {
30 return *arm_interface;
31 }
32
33 Kernel::Scheduler& Scheduler() {
34 return *scheduler;
35 }
36
37private:
38 void Reschedule();
39
40 std::shared_ptr<ARM_Interface> arm_interface;
41 std::unique_ptr<Kernel::Scheduler> scheduler;
42
43 bool reschedule_pending{};
44};
45
46} // namespace Core