core: Move common CPU core things to its own class.
This commit is contained in:
		
							parent
							
								
									5e9c547952
								
							
						
					
					
						commit
						5590245930
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								src/core/core_cpu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/core/core_cpu.cpp
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
							
								
								
									
										46
									
								
								src/core/core_cpu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/core/core_cpu.h
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user