diff --git a/src/xenia/base/clock_posix.cc b/src/xenia/base/clock_posix.cc new file mode 100644 index 000000000..6fb2f652a --- /dev/null +++ b/src/xenia/base/clock_posix.cc @@ -0,0 +1,46 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/clock.h" + +#include +#include + +namespace xe { + +uint64_t Clock::host_tick_frequency() { + timespec res; + clock_getres(CLOCK_MONOTONIC_RAW, &res); + + return uint64_t(res.tv_sec) + uint64_t(res.tv_nsec) * 1000000000ull; +} + +uint64_t Clock::QueryHostTickCount() { + timespec res; + clock_gettime(CLOCK_MONOTONIC_RAW, &res); + + return uint64_t(res.tv_sec) + uint64_t(res.tv_nsec) * 1000000000ull; +} + +uint64_t Clock::QueryHostSystemTime() { + struct timeval tv; + gettimeofday(&tv, NULL); + + uint64_t ret = tv.tv_usec; + ret /= 1000; // usec -> msec + + ret += (tv.tv_sec * 1000); // sec -> msec + return ret; +} + +uint32_t Clock::QueryHostUptimeMillis() { + return uint32_t(QueryHostTickCount() / (host_tick_frequency() / 1000)); +} + +} // namespace xe \ No newline at end of file diff --git a/src/xenia/base/debugging_posix.cc b/src/xenia/base/debugging_posix.cc new file mode 100644 index 000000000..f002c5ed2 --- /dev/null +++ b/src/xenia/base/debugging_posix.cc @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/debugging.h" + +#include +#include "xenia/base/string_buffer.h" + +namespace xe { +namespace debugging { + +bool IsDebuggerAttached() { return false; } +void Break() { raise(SIGTRAP); } + +void DebugPrint(const char* fmt, ...) { + StringBuffer buff; + + va_list va; + va_start(va, fmt); + buff.AppendVarargs(fmt, va); + va_end(va); + + // OutputDebugStringA(buff.GetString()); +} + +} // namespace debugging +} // namespace xe diff --git a/src/xenia/base/exception_handler_posix.cc b/src/xenia/base/exception_handler_posix.cc new file mode 100644 index 000000000..5c3aa81f0 --- /dev/null +++ b/src/xenia/base/exception_handler_posix.cc @@ -0,0 +1,18 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/exception_handler.h" + +namespace xe { + +// TODO(DrChat): Exception handling on linux. +void ExceptionHandler::Install(Handler fn, void* data) {} +void ExceptionHandler::Uninstall(Handler fn, void* data) {} + +} // namespace xe \ No newline at end of file diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc new file mode 100644 index 000000000..a4e55fc5d --- /dev/null +++ b/src/xenia/base/filesystem_posix.cc @@ -0,0 +1,63 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/filesystem.h" +#include "xenia/base/logging.h" +#include "xenia/base/string.h" + +#include +#include +#include +#include + +namespace xe { +namespace filesystem { + +bool PathExists(const std::wstring& path) { + struct stat st; + return stat(xe::to_string(path).c_str(), &st) == 0; +} + +FILE* OpenFile(const std::wstring& path, const char* mode) { + auto fixed_path = xe::fix_path_separators(path); + return fopen(xe::to_string(fixed_path).c_str(), mode); +} + +bool CreateFolder(const std::wstring& path) { + return mkdir(xe::to_string(path).c_str(), 0774); +} + +std::vector ListFiles(const std::wstring& path) { + std::vector result; + + DIR* dir = opendir(xe::to_string(path).c_str()); + if (!dir) { + return result; + } + + while (auto ent = readdir(dir)) { + FileInfo info; + std::memset(&info, 0, sizeof(info)); + if (ent->d_type == DT_DIR) { + info.type = FileInfo::Type::kDirectory; + info.total_size = 0; + } else { + info.type = FileInfo::Type::kFile; + info.total_size = 0; // TODO(DrChat): Find a way to get this + } + + info.name = xe::to_wstring(ent->d_name); + result.push_back(info); + } + + return result; +} + +} // namespace filesystem +} // namespace xe \ No newline at end of file diff --git a/src/xenia/base/logging.cc b/src/xenia/base/logging.cc index 720bf271c..b81ff0b91 100644 --- a/src/xenia/base/logging.cc +++ b/src/xenia/base/logging.cc @@ -53,7 +53,6 @@ class Logger { file_ = xe::filesystem::OpenFile(file_path, "wt"); } - flush_event_ = xe::threading::Event::CreateAutoResetEvent(false); write_thread_ = xe::threading::Thread::Create({}, [this]() { WriteThread(); }); write_thread_->set_name("xe::FileLogSink Writer"); @@ -61,7 +60,6 @@ class Logger { ~Logger() { running_ = false; - flush_event_->Set(); xe::threading::Wait(write_thread_.get(), true); fflush(file_); fclose(file_); @@ -113,9 +111,6 @@ class Logger { continue; } } - - // Kick the consumer thread - flush_event_->Set(); } private: @@ -139,6 +134,7 @@ class Logger { void WriteThread() { RingBuffer rb(buffer_, kBufferSize); + uint32_t idle_loops = 0; while (running_) { bool did_write = false; rb.set_write_offset(write_tail_); @@ -197,9 +193,16 @@ class Logger { if (FLAGS_flush_log) { fflush(file_); } + + idle_loops = 0; + } else { + if (idle_loops > 1000) { + // Introduce a waiting period. + xe::threading::Sleep(std::chrono::milliseconds(50)); + } + + idle_loops++; } - xe::threading::Wait(flush_event_.get(), true, - std::chrono::milliseconds(1)); } } @@ -210,7 +213,6 @@ class Logger { FILE* file_ = nullptr; std::atomic running_; - std::unique_ptr flush_event_; std::unique_ptr write_thread_; }; diff --git a/src/xenia/base/mapped_memory_posix.cc b/src/xenia/base/mapped_memory_posix.cc index 07c80f4d6..6d48a0157 100644 --- a/src/xenia/base/mapped_memory_posix.cc +++ b/src/xenia/base/mapped_memory_posix.cc @@ -74,4 +74,10 @@ std::unique_ptr MappedMemory::Open(const std::wstring& path, return std::move(mm); } +std::unique_ptr ChunkedMappedMemoryWriter::Open( + const std::wstring& path, size_t chunk_size, bool low_address_space) { + // TODO(DrChat) + return nullptr; +} + } // namespace xe diff --git a/src/xenia/base/memory_posix.cc b/src/xenia/base/memory_posix.cc new file mode 100644 index 000000000..d6b0dd062 --- /dev/null +++ b/src/xenia/base/memory_posix.cc @@ -0,0 +1,57 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/memory.h" + +#include + +namespace xe { +namespace memory { + +size_t page_size() { return getpagesize(); } +size_t allocation_granularity() { return page_size(); } + +void* AllocFixed(void* base_address, size_t length, + AllocationType allocation_type, PageAccess access) { + return nullptr; +} + +bool DeallocFixed(void* base_address, size_t length, + DeallocationType deallocation_type) { + return false; +} + +bool Protect(void* base_address, size_t length, PageAccess access, + PageAccess* out_old_access) { + return false; +} + +bool QueryProtect(void* base_address, size_t& length, PageAccess& access_out) { + return false; +} + +FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, + PageAccess access, bool commit) { + return nullptr; +} + +void CloseFileMappingHandle(FileMappingHandle handle) {} + +void* MapFileView(FileMappingHandle handle, void* base_address, size_t length, + PageAccess access, size_t file_offset) { + return nullptr; +} + +bool UnmapFileView(FileMappingHandle handle, void* base_address, + size_t length) { + return false; +} + +} // namespace memory +} // namespace xe diff --git a/src/xenia/base/platform_posix.h b/src/xenia/base/platform_posix.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 4b60baaf7..7f264e644 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -7,20 +7,24 @@ ****************************************************************************** */ +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" #include "xenia/base/threading.h" #include +#include +#include #include +#include namespace xe { namespace threading { // uint64_t ticks() { return mach_absolute_time(); } -// uint32_t current_thread_id() { -// mach_port_t tid = pthread_mach_thread_np(pthread_self()); -// return static_cast(tid); -// } +uint32_t current_thread_system_id() { + return static_cast(syscall(SYS_gettid)); +} void set_name(const std::string& name) { pthread_setname_np(pthread_self(), name.c_str()); @@ -36,5 +40,103 @@ void Sleep(std::chrono::microseconds duration) { // TODO(benvanik): spin while rmtp >0? } +template +class PosixHandle : public T { + public: + explicit PosixHandle(pthread_t handle) : handle_(handle) {} + ~PosixHandle() override {} + + protected: + void* native_handle() const override { + return reinterpret_cast(handle_); + } + + pthread_t handle_; +}; + +class PosixThread : public PosixHandle { + public: + explicit PosixThread(pthread_t handle) : PosixHandle(handle) {} + ~PosixThread() = default; + + void set_name(std::string name) override { + // TODO(DrChat) + } + + uint32_t system_id() const override { return 0; } + + // TODO(DrChat) + uint64_t affinity_mask() override { return 0; } + void set_affinity_mask(uint64_t mask) override { assert_always(); } + + int priority() override { + int policy; + struct sched_param param; + int ret = pthread_getschedparam(handle_, &policy, ¶m); + if (ret != 0) { + return -1; + } + + return param.sched_priority; + } + + void set_priority(int new_priority) override { + struct sched_param param; + param.sched_priority = new_priority; + int ret = pthread_setschedparam(handle_, SCHED_FIFO, ¶m); + } + + // TODO(DrChat) + void QueueUserCallback(std::function callback) override { + assert_always(); + } + + bool Resume(uint32_t* out_new_suspend_count = nullptr) override { + assert_always(); + return false; + } + + bool Suspend(uint32_t* out_previous_suspend_count = nullptr) override { + assert_always(); + return false; + } + + void Terminate(int exit_code) override {} +}; + +thread_local std::unique_ptr current_thread_ = nullptr; + +struct ThreadStartData { + std::function start_routine; +}; +void* ThreadStartRoutine(void* parameter) { + current_thread_ = std::make_unique(::pthread_self()); + + auto start_data = reinterpret_cast(parameter); + start_data->start_routine(); + delete start_data; + return 0; +} + +std::unique_ptr Thread::Create(CreationParameters params, + std::function start_routine) { + auto start_data = new ThreadStartData({std::move(start_routine)}); + + assert_false(params.create_suspended); + pthread_t handle; + pthread_attr_t attr; + pthread_attr_init(&attr); + int ret = pthread_create(&handle, &attr, ThreadStartRoutine, start_data); + if (ret != 0) { + // TODO(benvanik): pass back? + auto last_error = errno; + XELOGE("Unable to pthread_create: %d", last_error); + delete start_data; + return nullptr; + } + + return std::make_unique(handle); +} + } // namespace threading } // namespace xe diff --git a/src/xenia/cpu/backend/backend.cc b/src/xenia/cpu/backend/backend.cc index 01c696c34..6773d5c99 100644 --- a/src/xenia/cpu/backend/backend.cc +++ b/src/xenia/cpu/backend/backend.cc @@ -15,14 +15,13 @@ namespace xe { namespace cpu { namespace backend { -Backend::Backend(Processor* processor) - : processor_(processor), code_cache_(nullptr) { - std::memset(&machine_info_, 0, sizeof(machine_info_)); -} - +Backend::Backend() { std::memset(&machine_info_, 0, sizeof(machine_info_)); } Backend::~Backend() = default; -bool Backend::Initialize() { return true; } +bool Backend::Initialize(Processor* processor) { + processor_ = processor; + return true; +} void* Backend::AllocThreadData() { return nullptr; } diff --git a/src/xenia/cpu/backend/backend.h b/src/xenia/cpu/backend/backend.h index 4d6f68346..054d7e752 100644 --- a/src/xenia/cpu/backend/backend.h +++ b/src/xenia/cpu/backend/backend.h @@ -34,14 +34,14 @@ class CodeCache; class Backend { public: - explicit Backend(Processor* processor); + explicit Backend(); virtual ~Backend(); Processor* processor() const { return processor_; } const MachineInfo* machine_info() const { return &machine_info_; } CodeCache* code_cache() const { return code_cache_; } - virtual bool Initialize(); + virtual bool Initialize(Processor* processor); virtual void* AllocThreadData(); virtual void FreeThreadData(void* thread_data); @@ -65,9 +65,9 @@ class Backend { virtual void UninstallBreakpoint(Breakpoint* breakpoint) {} protected: - Processor* processor_; + Processor* processor_ = nullptr; MachineInfo machine_info_; - CodeCache* code_cache_; + CodeCache* code_cache_ = nullptr; }; } // namespace backend diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc index 5245e82da..7739c9519 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.cc +++ b/src/xenia/cpu/backend/x64/x64_backend.cc @@ -42,8 +42,7 @@ class X64ThunkEmitter : public X64Emitter { ResolveFunctionThunk EmitResolveFunctionThunk(); }; -X64Backend::X64Backend(Processor* processor) - : Backend(processor), code_cache_(nullptr) { +X64Backend::X64Backend() : Backend(), code_cache_(nullptr) { if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) { assert_always("Failed to initialize capstone"); } @@ -61,8 +60,8 @@ X64Backend::~X64Backend() { ExceptionHandler::Uninstall(&ExceptionCallbackThunk, this); } -bool X64Backend::Initialize() { - if (!Backend::Initialize()) { +bool X64Backend::Initialize(Processor* processor) { + if (!Backend::Initialize(processor)) { return false; } diff --git a/src/xenia/cpu/backend/x64/x64_backend.h b/src/xenia/cpu/backend/x64/x64_backend.h index d0e9e2627..19c4caab3 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.h +++ b/src/xenia/cpu/backend/x64/x64_backend.h @@ -38,7 +38,7 @@ class X64Backend : public Backend { public: static const uint32_t kForceReturnAddress = 0x9FFF0000u; - explicit X64Backend(Processor* processor); + explicit X64Backend(); ~X64Backend() override; X64CodeCache* code_cache() const { return code_cache_.get(); } @@ -53,7 +53,7 @@ class X64Backend : public Backend { return resolve_function_thunk_; } - bool Initialize() override; + bool Initialize(Processor* processor) override; void CommitExecutableRange(uint32_t guest_low, uint32_t guest_high) override; diff --git a/src/xenia/cpu/backend/x64/x64_code_cache_posix.cc b/src/xenia/cpu/backend/x64/x64_code_cache_posix.cc new file mode 100644 index 000000000..490ab2ce9 --- /dev/null +++ b/src/xenia/cpu/backend/x64/x64_code_cache_posix.cc @@ -0,0 +1,51 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/cpu/backend/x64/x64_code_cache.h" + +namespace xe { +namespace cpu { +namespace backend { +namespace x64 { + +class PosixX64CodeCache : public X64CodeCache { + public: + PosixX64CodeCache(); + ~PosixX64CodeCache() override; + + bool Initialize() override; + + void* LookupUnwindInfo(uint64_t host_pc) override { return nullptr; } + + private: + /* + UnwindReservation RequestUnwindReservation(uint8_t* entry_address) override; + void PlaceCode(uint32_t guest_address, void* machine_code, size_t code_size, + size_t stack_size, void* code_address, + UnwindReservation unwind_reservation) override; + + void InitializeUnwindEntry(uint8_t* unwind_entry_address, + size_t unwind_table_slot, void* code_address, + size_t code_size, size_t stack_size); + */ +}; + +std::unique_ptr X64CodeCache::Create() { + return std::make_unique(); +} + +PosixX64CodeCache::PosixX64CodeCache() = default; +PosixX64CodeCache::~PosixX64CodeCache() = default; + +bool PosixX64CodeCache::Initialize() { return X64CodeCache::Initialize(); } + +} // namespace x64 +} // namespace backend +} // namespace cpu +} // namespace xe \ No newline at end of file diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc index 08e015614..443159f92 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc @@ -15,6 +15,7 @@ #include "xenia/base/math.h" #include "xenia/base/platform.h" #include "xenia/cpu/backend/x64/x64_backend.h" +#include "xenia/cpu/cpu_flags.h" #include "xenia/cpu/ppc/ppc_context.h" #include "xenia/cpu/ppc/ppc_frontend.h" #include "xenia/cpu/processor.h" @@ -188,9 +189,25 @@ class TestRunner { // Reset memory. memory->Reset(); + std::unique_ptr backend; + if (!backend) { +#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND + if (FLAGS_cpu == "x64") { + backend.reset(new xe::cpu::backend::x64::X64Backend()); + } +#endif // XENIA_HAS_X64_BACKEND + if (FLAGS_cpu == "any") { +#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND + if (!backend) { + backend.reset(new xe::cpu::backend::x64::X64Backend()); + } +#endif // XENIA_HAS_X64_BACKEND + } + } + // Setup a fresh processor. processor.reset(new Processor(memory.get(), nullptr)); - processor->Setup(); + processor->Setup(std::move(backend)); processor->set_debug_info_flags(DebugInfoFlags::kDebugInfoAll); // Load the binary module. diff --git a/src/xenia/cpu/ppc/testing/premake5.lua b/src/xenia/cpu/ppc/testing/premake5.lua index 57a79aa40..c1f4f4cc9 100644 --- a/src/xenia/cpu/ppc/testing/premake5.lua +++ b/src/xenia/cpu/ppc/testing/premake5.lua @@ -7,9 +7,9 @@ project("xenia-cpu-ppc-tests") kind("ConsoleApp") language("C++") links({ + "xenia-core", "xenia-cpu-backend-x64", "xenia-cpu", - "xenia-core", "xenia-base", "gflags", "capstone", -- cpu-backend-x64 diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 2877a79b7..8088e4bb1 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -95,7 +95,7 @@ Processor::~Processor() { } } -bool Processor::Setup() { +bool Processor::Setup(std::unique_ptr backend) { // TODO(benvanik): query mode from debugger? debug_info_flags_ = 0; @@ -113,26 +113,10 @@ bool Processor::Setup() { return false; } - std::unique_ptr backend; - if (!backend) { -#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND - if (FLAGS_cpu == "x64") { - backend.reset(new xe::cpu::backend::x64::X64Backend(this)); - } -#endif // XENIA_HAS_X64_BACKEND - if (FLAGS_cpu == "any") { -#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND - if (!backend) { - backend.reset(new xe::cpu::backend::x64::X64Backend(this)); - } -#endif // XENIA_HAS_X64_BACKEND - } - } - if (!backend) { return false; } - if (!backend->Initialize()) { + if (!backend->Initialize(this)) { return false; } if (!frontend->Initialize()) { diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 4ea6d4429..57f714593 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -71,7 +71,7 @@ class Processor { backend::Backend* backend() const { return backend_.get(); } ExportResolver* export_resolver() const { return export_resolver_; } - bool Setup(); + bool Setup(std::unique_ptr backend); // Runs any pre-launch logic once the module and thread have been setup. void PreLaunch(); diff --git a/src/xenia/cpu/stack_walker_posix.cc b/src/xenia/cpu/stack_walker_posix.cc new file mode 100644 index 000000000..eba6e30cc --- /dev/null +++ b/src/xenia/cpu/stack_walker_posix.cc @@ -0,0 +1,24 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2017 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/cpu/stack_walker.h" + +#include "xenia/base/logging.h" + +namespace xe { +namespace cpu { + +std::unique_ptr StackWalker::Create( + backend::CodeCache* code_cache) { + XELOGD("Stack walker unimplemented on posix"); + return nullptr; +} + +} // namespace cpu +} // namespace xe \ No newline at end of file diff --git a/src/xenia/cpu/testing/util.h b/src/xenia/cpu/testing/util.h index c04f0a756..075903455 100644 --- a/src/xenia/cpu/testing/util.h +++ b/src/xenia/cpu/testing/util.h @@ -39,8 +39,9 @@ class TestFunction { #if XENIA_TEST_X64 { + auto backend = std::make_unique(); auto processor = std::make_unique(memory.get(), nullptr); - processor->Setup(); + processor->Setup(std::move(backend)); processors.emplace_back(std::move(processor)); } #endif // XENIA_TEST_X64 diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index ef9c4694d..d90530cdb 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -23,6 +23,8 @@ #include "xenia/base/profiling.h" #include "xenia/base/string.h" #include "xenia/cpu/backend/code_cache.h" +#include "xenia/cpu/backend/x64/x64_backend.h" +#include "xenia/cpu/cpu_flags.h" #include "xenia/cpu/thread_state.h" #include "xenia/gpu/graphics_system.h" #include "xenia/hid/input_driver.h" @@ -107,10 +109,26 @@ X_STATUS Emulator::Setup( // Shared export resolver used to attach and query for HLE exports. export_resolver_ = std::make_unique(); + std::unique_ptr backend; + if (!backend) { +#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND + if (FLAGS_cpu == "x64") { + backend.reset(new xe::cpu::backend::x64::X64Backend()); + } +#endif // XENIA_HAS_X64_BACKEND + if (FLAGS_cpu == "any") { +#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND + if (!backend) { + backend.reset(new xe::cpu::backend::x64::X64Backend()); + } +#endif // XENIA_HAS_X64_BACKEND + } + } + // Initialize the CPU. processor_ = std::make_unique(memory_.get(), export_resolver_.get()); - if (!processor_->Setup()) { + if (!processor_->Setup(std::move(backend))) { return X_STATUS_UNSUCCESSFUL; }