xenia-cpu-ppc-tests is now building on linux
This commit is contained in:
parent
11ae05155d
commit
d43e2c7ff8
|
@ -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 <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
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
|
|
@ -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 <signal.h>
|
||||
#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
|
|
@ -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
|
|
@ -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 <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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<FileInfo> ListFiles(const std::wstring& path) {
|
||||
std::vector<FileInfo> 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
|
|
@ -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<bool> running_;
|
||||
std::unique_ptr<xe::threading::Event> flush_event_;
|
||||
std::unique_ptr<xe::threading::Thread> write_thread_;
|
||||
};
|
||||
|
||||
|
|
|
@ -74,4 +74,10 @@ std::unique_ptr<MappedMemory> MappedMemory::Open(const std::wstring& path,
|
|||
return std::move(mm);
|
||||
}
|
||||
|
||||
std::unique_ptr<ChunkedMappedMemoryWriter> ChunkedMappedMemoryWriter::Open(
|
||||
const std::wstring& path, size_t chunk_size, bool low_address_space) {
|
||||
// TODO(DrChat)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
|
|
@ -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 <unistd.h>
|
||||
|
||||
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
|
|
@ -7,20 +7,24 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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<uint32_t>(tid);
|
||||
// }
|
||||
uint32_t current_thread_system_id() {
|
||||
return static_cast<uint32_t>(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 <typename T>
|
||||
class PosixHandle : public T {
|
||||
public:
|
||||
explicit PosixHandle(pthread_t handle) : handle_(handle) {}
|
||||
~PosixHandle() override {}
|
||||
|
||||
protected:
|
||||
void* native_handle() const override {
|
||||
return reinterpret_cast<void*>(handle_);
|
||||
}
|
||||
|
||||
pthread_t handle_;
|
||||
};
|
||||
|
||||
class PosixThread : public PosixHandle<Thread> {
|
||||
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<void()> 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<PosixThread> current_thread_ = nullptr;
|
||||
|
||||
struct ThreadStartData {
|
||||
std::function<void()> start_routine;
|
||||
};
|
||||
void* ThreadStartRoutine(void* parameter) {
|
||||
current_thread_ = std::make_unique<PosixThread>(::pthread_self());
|
||||
|
||||
auto start_data = reinterpret_cast<ThreadStartData*>(parameter);
|
||||
start_data->start_routine();
|
||||
delete start_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<Thread> Thread::Create(CreationParameters params,
|
||||
std::function<void()> 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<PosixThread>(handle);
|
||||
}
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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> X64CodeCache::Create() {
|
||||
return std::make_unique<PosixX64CodeCache>();
|
||||
}
|
||||
|
||||
PosixX64CodeCache::PosixX64CodeCache() = default;
|
||||
PosixX64CodeCache::~PosixX64CodeCache() = default;
|
||||
|
||||
bool PosixX64CodeCache::Initialize() { return X64CodeCache::Initialize(); }
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -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<xe::cpu::backend::Backend> 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -95,7 +95,7 @@ Processor::~Processor() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Processor::Setup() {
|
||||
bool Processor::Setup(std::unique_ptr<backend::Backend> backend) {
|
||||
// TODO(benvanik): query mode from debugger?
|
||||
debug_info_flags_ = 0;
|
||||
|
||||
|
@ -113,26 +113,10 @@ bool Processor::Setup() {
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<xe::cpu::backend::Backend> 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()) {
|
||||
|
|
|
@ -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::Backend> backend);
|
||||
|
||||
// Runs any pre-launch logic once the module and thread have been setup.
|
||||
void PreLaunch();
|
||||
|
|
|
@ -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> StackWalker::Create(
|
||||
backend::CodeCache* code_cache) {
|
||||
XELOGD("Stack walker unimplemented on posix");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
|
@ -39,8 +39,9 @@ class TestFunction {
|
|||
|
||||
#if XENIA_TEST_X64
|
||||
{
|
||||
auto backend = std::make_unique<xe::cpu::backend::x64::X64Backend>();
|
||||
auto processor = std::make_unique<Processor>(memory.get(), nullptr);
|
||||
processor->Setup();
|
||||
processor->Setup(std::move(backend));
|
||||
processors.emplace_back(std::move(processor));
|
||||
}
|
||||
#endif // XENIA_TEST_X64
|
||||
|
|
|
@ -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<xe::cpu::ExportResolver>();
|
||||
|
||||
std::unique_ptr<xe::cpu::backend::Backend> 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<xe::cpu::Processor>(memory_.get(),
|
||||
export_resolver_.get());
|
||||
if (!processor_->Setup()) {
|
||||
if (!processor_->Setup(std::move(backend))) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue