Merging Runtime into Processor.

This commit is contained in:
Ben Vanik 2015-05-03 22:28:25 -07:00
parent 4c8f3501ad
commit 78921c1a7e
56 changed files with 441 additions and 543 deletions

View File

@ -90,8 +90,7 @@ X_STATUS AudioSystem::Setup() {
registers_.next_context = 1; registers_.next_context = 1;
// Setup worker thread state. This lets us make calls into guest code. // Setup worker thread state. This lets us make calls into guest code.
thread_state_ = thread_state_ = new ThreadState(emulator_->processor(), 0, 0, 16 * 1024, 0);
new ThreadState(emulator_->processor()->runtime(), 0, 0, 16 * 1024, 0);
thread_state_->set_name("Audio Worker"); thread_state_->set_name("Audio Worker");
thread_block_ = memory()->SystemHeapAlloc(2048); thread_block_ = memory()->SystemHeapAlloc(2048);
thread_state_->context()->r[13] = thread_block_; thread_state_->context()->r[13] = thread_block_;

View File

@ -17,7 +17,6 @@ namespace cpu {
class DebugInfo; class DebugInfo;
class Function; class Function;
class FunctionInfo; class FunctionInfo;
class Runtime;
namespace hir { namespace hir {
class HIRBuilder; class HIRBuilder;
} // namespace hir } // namespace hir

View File

@ -13,9 +13,7 @@ namespace xe {
namespace cpu { namespace cpu {
namespace backend { namespace backend {
using xe::cpu::Runtime; Backend::Backend(Processor* processor) : processor_(processor) {
Backend::Backend(Runtime* runtime) : runtime_(runtime) {
memset(&machine_info_, 0, sizeof(machine_info_)); memset(&machine_info_, 0, sizeof(machine_info_));
} }

View File

@ -16,7 +16,7 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Runtime; class Processor;
} // namespace cpu } // namespace cpu
} // namespace xe } // namespace xe
@ -28,10 +28,10 @@ class Assembler;
class Backend { class Backend {
public: public:
Backend(Runtime* runtime); Backend(Processor* processor);
virtual ~Backend(); virtual ~Backend();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
const MachineInfo* machine_info() const { return &machine_info_; } const MachineInfo* machine_info() const { return &machine_info_; }
virtual int Initialize(); virtual int Initialize();
@ -42,7 +42,7 @@ class Backend {
virtual std::unique_ptr<Assembler> CreateAssembler() = 0; virtual std::unique_ptr<Assembler> CreateAssembler() = 0;
protected: protected:
Runtime* runtime_; Processor* processor_;
MachineInfo machine_info_; MachineInfo machine_info_;
}; };

View File

@ -15,7 +15,7 @@
#include "xenia/cpu/backend/x64/x64_function.h" #include "xenia/cpu/backend/x64/x64_function.h"
#include "xenia/cpu/hir/hir_builder.h" #include "xenia/cpu/hir/hir_builder.h"
#include "xenia/cpu/hir/label.h" #include "xenia/cpu/hir/label.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace BE { namespace BE {

View File

@ -19,9 +19,8 @@ namespace cpu {
namespace backend { namespace backend {
namespace x64 { namespace x64 {
using xe::cpu::Runtime; X64Backend::X64Backend(Processor* processor)
: Backend(processor), code_cache_(nullptr) {}
X64Backend::X64Backend(Runtime* runtime) : Backend(runtime), code_cache_(0) {}
X64Backend::~X64Backend() { delete code_cache_; } X64Backend::~X64Backend() { delete code_cache_; }

View File

@ -26,7 +26,7 @@ typedef void* (*GuestToHostThunk)(void* target, void* arg0, void* arg1);
class X64Backend : public Backend { class X64Backend : public Backend {
public: public:
X64Backend(Runtime* runtime); X64Backend(Processor* processor);
~X64Backend() override; ~X64Backend() override;
X64CodeCache* code_cache() const { return code_cache_; } X64CodeCache* code_cache() const { return code_cache_; }

View File

@ -22,7 +22,7 @@
#include "xenia/cpu/cpu-private.h" #include "xenia/cpu/cpu-private.h"
#include "xenia/cpu/debug_info.h" #include "xenia/cpu/debug_info.h"
#include "xenia/cpu/hir/hir_builder.h" #include "xenia/cpu/hir/hir_builder.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/cpu/symbol_info.h" #include "xenia/cpu/symbol_info.h"
#include "xenia/cpu/thread_state.h" #include "xenia/cpu/thread_state.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
@ -60,7 +60,7 @@ const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
: CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator), : CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator),
runtime_(backend->runtime()), processor_(backend->processor()),
backend_(backend), backend_(backend),
code_cache_(backend->code_cache()), code_cache_(backend->code_cache()),
allocator_(allocator), allocator_(allocator),
@ -217,7 +217,8 @@ void X64Emitter::MarkSourceOffset(const Instr* i) {
void X64Emitter::EmitGetCurrentThreadId() { void X64Emitter::EmitGetCurrentThreadId() {
// rcx must point to context. We could fetch from the stack if needed. // rcx must point to context. We could fetch from the stack if needed.
mov(ax, word[rcx + runtime_->frontend()->context_info()->thread_id_offset()]); mov(ax,
word[rcx + processor_->frontend()->context_info()->thread_id_offset()]);
} }
void X64Emitter::EmitTraceUserCallReturn() {} void X64Emitter::EmitTraceUserCallReturn() {}
@ -279,7 +280,7 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
// Resolve function. This will demand compile as required. // Resolve function. This will demand compile as required.
Function* fn = NULL; Function* fn = NULL;
thread_state->runtime()->ResolveFunction(symbol_info->address(), &fn); thread_state->processor()->ResolveFunction(symbol_info->address(), &fn);
assert_not_null(fn); assert_not_null(fn);
auto x64_fn = static_cast<X64Function*>(fn); auto x64_fn = static_cast<X64Function*>(fn);
uint64_t addr = reinterpret_cast<uint64_t>(x64_fn->machine_code()); uint64_t addr = reinterpret_cast<uint64_t>(x64_fn->machine_code());
@ -361,7 +362,7 @@ uint64_t ResolveFunctionAddress(void* raw_context, uint32_t target_address) {
assert_not_zero(target_address); assert_not_zero(target_address);
Function* fn = NULL; Function* fn = NULL;
thread_state->runtime()->ResolveFunction(target_address, &fn); thread_state->processor()->ResolveFunction(target_address, &fn);
assert_not_null(fn); assert_not_null(fn);
auto x64_fn = static_cast<X64Function*>(fn); auto x64_fn = static_cast<X64Function*>(fn);
uint64_t addr = reinterpret_cast<uint64_t>(x64_fn->machine_code()); uint64_t addr = reinterpret_cast<uint64_t>(x64_fn->machine_code());

View File

@ -20,7 +20,7 @@ namespace xe {
namespace cpu { namespace cpu {
class DebugInfo; class DebugInfo;
class FunctionInfo; class FunctionInfo;
class Runtime; class Processor;
class SymbolInfo; class SymbolInfo;
namespace hir { namespace hir {
class HIRBuilder; class HIRBuilder;
@ -101,7 +101,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
X64Emitter(X64Backend* backend, XbyakAllocator* allocator); X64Emitter(X64Backend* backend, XbyakAllocator* allocator);
virtual ~X64Emitter(); virtual ~X64Emitter();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
X64Backend* backend() const { return backend_; } X64Backend* backend() const { return backend_; }
const Xbyak::util::Cpu* cpu() const { return &cpu_; } const Xbyak::util::Cpu* cpu() const { return &cpu_; }
@ -187,7 +187,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
void EmitTraceUserCallReturn(); void EmitTraceUserCallReturn();
protected: protected:
Runtime* runtime_; Processor* processor_;
X64Backend* backend_; X64Backend* backend_;
X64CodeCache* code_cache_; X64CodeCache* code_cache_;
XbyakAllocator* allocator_; XbyakAllocator* allocator_;

View File

@ -10,7 +10,7 @@
#include "xenia/cpu/backend/x64/x64_function.h" #include "xenia/cpu/backend/x64/x64_function.h"
#include "xenia/cpu/backend/x64/x64_backend.h" #include "xenia/cpu/backend/x64/x64_backend.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/cpu/thread_state.h" #include "xenia/cpu/thread_state.h"
namespace xe { namespace xe {
@ -35,7 +35,8 @@ int X64Function::AddBreakpointImpl(Breakpoint* breakpoint) { return 0; }
int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; } int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) { int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
auto backend = (X64Backend*)thread_state->runtime()->backend(); auto backend =
reinterpret_cast<X64Backend*>(thread_state->processor()->backend());
auto thunk = backend->host_to_guest_thunk(); auto thunk = backend->host_to_guest_thunk();
thunk(machine_code_, thread_state->context(), thunk(machine_code_, thread_state->context(),
reinterpret_cast<void*>(uintptr_t(return_address))); reinterpret_cast<void*>(uintptr_t(return_address)));

View File

@ -30,7 +30,7 @@
#include "xenia/cpu/backend/x64/x64_emitter.h" #include "xenia/cpu/backend/x64/x64_emitter.h"
#include "xenia/cpu/backend/x64/x64_tracers.h" #include "xenia/cpu/backend/x64/x64_tracers.h"
#include "xenia/cpu/hir/hir_builder.h" #include "xenia/cpu/hir/hir_builder.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {

View File

@ -11,7 +11,7 @@
#include "xenia/base/vec128.h" #include "xenia/base/vec128.h"
#include "xenia/cpu/backend/x64/x64_emitter.h" #include "xenia/cpu/backend/x64/x64_emitter.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/cpu/thread_state.h" #include "xenia/cpu/thread_state.h"
using namespace xe; using namespace xe;

View File

@ -16,10 +16,7 @@ namespace xe {
namespace cpu { namespace cpu {
namespace compiler { namespace compiler {
using xe::cpu::hir::HIRBuilder; Compiler::Compiler(Processor* processor) : processor_(processor) {}
using xe::cpu::Runtime;
Compiler::Compiler(Runtime* runtime) : runtime_(runtime) {}
Compiler::~Compiler() { Reset(); } Compiler::~Compiler() { Reset(); }
@ -30,7 +27,7 @@ void Compiler::AddPass(std::unique_ptr<CompilerPass> pass) {
void Compiler::Reset() {} void Compiler::Reset() {}
int Compiler::Compile(HIRBuilder* builder) { int Compiler::Compile(xe::cpu::hir::HIRBuilder* builder) {
// TODO(benvanik): sophisticated stuff. Run passes in parallel, run until they // TODO(benvanik): sophisticated stuff. Run passes in parallel, run until they
// stop changing things, etc. // stop changing things, etc.
for (size_t i = 0; i < passes_.size(); ++i) { for (size_t i = 0; i < passes_.size(); ++i) {

View File

@ -18,7 +18,7 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Runtime; class Processor;
} // namespace cpu } // namespace cpu
} // namespace xe } // namespace xe
@ -30,10 +30,10 @@ class CompilerPass;
class Compiler { class Compiler {
public: public:
Compiler(Runtime* runtime); Compiler(Processor* processor);
~Compiler(); ~Compiler();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
Arena* scratch_arena() { return &scratch_arena_; } Arena* scratch_arena() { return &scratch_arena_; }
void AddPass(std::unique_ptr<CompilerPass> pass); void AddPass(std::unique_ptr<CompilerPass> pass);
@ -43,7 +43,7 @@ class Compiler {
int Compile(hir::HIRBuilder* builder); int Compile(hir::HIRBuilder* builder);
private: private:
Runtime* runtime_; Processor* processor_;
Arena scratch_arena_; Arena scratch_arena_;
std::vector<std::unique_ptr<CompilerPass>> passes_; std::vector<std::unique_ptr<CompilerPass>> passes_;

View File

@ -15,12 +15,12 @@ namespace xe {
namespace cpu { namespace cpu {
namespace compiler { namespace compiler {
CompilerPass::CompilerPass() : runtime_(0), compiler_(0) {} CompilerPass::CompilerPass() : processor_(nullptr), compiler_(nullptr) {}
CompilerPass::~CompilerPass() = default; CompilerPass::~CompilerPass() = default;
int CompilerPass::Initialize(Compiler* compiler) { int CompilerPass::Initialize(Compiler* compiler) {
runtime_ = compiler->runtime(); processor_ = compiler->processor();
compiler_ = compiler; compiler_ = compiler;
return 0; return 0;
} }

View File

@ -15,7 +15,7 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Runtime; class Processor;
} // namespace cpu } // namespace cpu
} // namespace xe } // namespace xe
@ -38,7 +38,7 @@ class CompilerPass {
Arena* scratch_arena() const; Arena* scratch_arena() const;
protected: protected:
Runtime* runtime_; Processor* processor_;
Compiler* compiler_; Compiler* compiler_;
}; };

View File

@ -11,7 +11,7 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/cpu/function.h" #include "xenia/cpu/function.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {
@ -98,7 +98,7 @@ int ConstantPropagationPass::Run(HIRBuilder* builder) {
case OPCODE_CALL_INDIRECT: case OPCODE_CALL_INDIRECT:
if (i->src1.value->IsConstant()) { if (i->src1.value->IsConstant()) {
FunctionInfo* symbol_info; FunctionInfo* symbol_info;
if (runtime_->LookupFunctionInfo( if (processor_->LookupFunctionInfo(
(uint32_t)i->src1.value->constant.i32, &symbol_info)) { (uint32_t)i->src1.value->constant.i32, &symbol_info)) {
break; break;
} }

View File

@ -12,7 +12,7 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
DEFINE_bool(store_all_context_values, false, DEFINE_bool(store_all_context_values, false,
@ -42,7 +42,7 @@ int ContextPromotionPass::Initialize(Compiler* compiler) {
} }
// This is a terrible implementation. // This is a terrible implementation.
ContextInfo* context_info = runtime_->frontend()->context_info(); ContextInfo* context_info = processor_->frontend()->context_info();
context_values_.resize(context_info->size()); context_values_.resize(context_info->size());
context_validity_.resize(static_cast<uint32_t>(context_info->size())); context_validity_.resize(static_cast<uint32_t>(context_info->size()));

View File

@ -11,7 +11,7 @@
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {

View File

@ -11,7 +11,7 @@
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {

View File

@ -13,7 +13,7 @@
#include "xenia/base/platform.h" #include "xenia/base/platform.h"
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
#if XE_COMPILER_MSVC #if XE_COMPILER_MSVC

View File

@ -11,7 +11,7 @@
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {

View File

@ -12,7 +12,7 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {

View File

@ -12,7 +12,7 @@
#include "xenia/base/platform.h" #include "xenia/base/platform.h"
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
#if XE_COMPILER_MSVC #if XE_COMPILER_MSVC

View File

@ -12,6 +12,8 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
DECLARE_string(processor_backend);
DECLARE_string(load_module_map); DECLARE_string(load_module_map);
DECLARE_string(dump_path); DECLARE_string(dump_path);

View File

@ -9,6 +9,8 @@
#include "xenia/cpu/cpu-private.h" #include "xenia/cpu/cpu-private.h"
DEFINE_string(processor_backend, "any", "CPU backend [any, x64].");
// Debugging: // Debugging:
DEFINE_string( DEFINE_string(
load_module_map, "", load_module_map, "",

View File

@ -13,9 +13,7 @@
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#include "xenia/cpu/function.h" #include "xenia/cpu/function.h"
#include "xenia/cpu/module.h" #include "xenia/cpu/module.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/cpu/runtime.h"
#include "xenia/cpu/thread_state.h" #include "xenia/cpu/thread_state.h"
#include "xenia/cpu/xex_module.h" #include "xenia/cpu/xex_module.h"

View File

@ -12,7 +12,7 @@
#include <mutex> #include <mutex>
#include "xenia/cpu/function.h" #include "xenia/cpu/function.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -22,7 +22,7 @@ Breakpoint::Breakpoint(Type type, uint32_t address)
Breakpoint::~Breakpoint() = default; Breakpoint::~Breakpoint() = default;
Debugger::Debugger(Runtime* runtime) : runtime_(runtime) {} Debugger::Debugger(Processor* processor) : processor_(processor) {}
Debugger::~Debugger() = default; Debugger::~Debugger() = default;
@ -82,7 +82,7 @@ int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
} }
// Find all functions that contain the breakpoint address. // Find all functions that contain the breakpoint address.
auto fns = runtime_->FindFunctionsWithAddress(breakpoint->address()); auto fns = processor_->FindFunctionsWithAddress(breakpoint->address());
// Add. // Add.
for (auto fn : fns) { for (auto fn : fns) {
@ -116,7 +116,7 @@ int Debugger::RemoveBreakpoint(Breakpoint* breakpoint) {
} }
// Find all functions that have the breakpoint set. // Find all functions that have the breakpoint set.
auto fns = runtime_->FindFunctionsWithAddress(breakpoint->address()); auto fns = processor_->FindFunctionsWithAddress(breakpoint->address());
// Remove. // Remove.
for (auto fn : fns) { for (auto fn : fns) {

View File

@ -24,7 +24,7 @@ namespace cpu {
class Debugger; class Debugger;
class Function; class Function;
class FunctionInfo; class FunctionInfo;
class Runtime; class Processor;
class Breakpoint { class Breakpoint {
public: public:
@ -78,10 +78,10 @@ class BreakpointHitEvent : public DebugEvent {
class Debugger { class Debugger {
public: public:
Debugger(Runtime* runtime); Debugger(Processor* processor);
~Debugger(); ~Debugger();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX); int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX);
int ResumeThread(uint32_t thread_id); int ResumeThread(uint32_t thread_id);
@ -107,7 +107,7 @@ class Debugger {
Delegate<BreakpointHitEvent> breakpoint_hit; Delegate<BreakpointHitEvent> breakpoint_hit;
private: private:
Runtime* runtime_; Processor* processor_;
std::mutex threads_lock_; std::mutex threads_lock_;
std::unordered_map<uint32_t, ThreadState*> threads_; std::unordered_map<uint32_t, ThreadState*> threads_;

View File

@ -16,7 +16,7 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Runtime; class Processor;
class ThreadState; class ThreadState;
} // namespace cpu } // namespace cpu
} // namespace xe } // namespace xe
@ -205,9 +205,9 @@ typedef struct alignas(64) PPCContext_s {
// Used to shuttle data into externs. Contents volatile. // Used to shuttle data into externs. Contents volatile.
uint64_t scratch; uint64_t scratch;
// Runtime-specific data pointer. Used on callbacks to get access to the // Processor-specific data pointer. Used on callbacks to get access to the
// current runtime and its data. // current runtime and its data.
Runtime* runtime; Processor* processor;
uint8_t* physical_membase; uint8_t* physical_membase;

View File

@ -13,7 +13,7 @@
#include "xenia/cpu/frontend/ppc_disasm.h" #include "xenia/cpu/frontend/ppc_disasm.h"
#include "xenia/cpu/frontend/ppc_emit.h" #include "xenia/cpu/frontend/ppc_emit.h"
#include "xenia/cpu/frontend/ppc_translator.h" #include "xenia/cpu/frontend/ppc_translator.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -42,7 +42,7 @@ void InitializeIfNeeded() {
void CleanupOnShutdown() {} void CleanupOnShutdown() {}
PPCFrontend::PPCFrontend(Runtime* runtime) : runtime_(runtime) { PPCFrontend::PPCFrontend(Processor* processor) : processor_(processor) {
InitializeIfNeeded(); InitializeIfNeeded();
std::unique_ptr<ContextInfo> context_info( std::unique_ptr<ContextInfo> context_info(
@ -57,7 +57,7 @@ PPCFrontend::~PPCFrontend() {
translator_pool_.Reset(); translator_pool_.Reset();
} }
Memory* PPCFrontend::memory() const { return runtime_->memory(); } Memory* PPCFrontend::memory() const { return processor_->memory(); }
void CheckGlobalLock(PPCContext* ppc_state, void* arg0, void* arg1) { void CheckGlobalLock(PPCContext* ppc_state, void* arg0, void* arg1) {
ppc_state->scratch = 0x8000; ppc_state->scratch = 0x8000;
@ -78,10 +78,10 @@ void HandleGlobalLock(PPCContext* ppc_state, void* arg0, void* arg1) {
int PPCFrontend::Initialize() { int PPCFrontend::Initialize() {
void* arg0 = reinterpret_cast<void*>(&builtins_.global_lock); void* arg0 = reinterpret_cast<void*>(&builtins_.global_lock);
void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_taken); void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_taken);
builtins_.check_global_lock = runtime_->DefineBuiltin( builtins_.check_global_lock = processor_->DefineBuiltin(
"CheckGlobalLock", (FunctionInfo::ExternHandler)CheckGlobalLock, arg0, "CheckGlobalLock", (FunctionInfo::ExternHandler)CheckGlobalLock, arg0,
arg1); arg1);
builtins_.handle_global_lock = runtime_->DefineBuiltin( builtins_.handle_global_lock = processor_->DefineBuiltin(
"HandleGlobalLock", (FunctionInfo::ExternHandler)HandleGlobalLock, arg0, "HandleGlobalLock", (FunctionInfo::ExternHandler)HandleGlobalLock, arg0,
arg1); arg1);

View File

@ -21,7 +21,7 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Runtime; class Processor;
} // namespace cpu } // namespace cpu
} // namespace xe } // namespace xe
@ -40,12 +40,12 @@ struct PPCBuiltins {
class PPCFrontend { class PPCFrontend {
public: public:
explicit PPCFrontend(Runtime* runtime); explicit PPCFrontend(Processor* processor);
~PPCFrontend(); ~PPCFrontend();
int Initialize(); int Initialize();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
Memory* memory() const; Memory* memory() const;
ContextInfo* context_info() const { return context_info_.get(); } ContextInfo* context_info() const { return context_info_.get(); }
PPCBuiltins* builtins() { return &builtins_; } PPCBuiltins* builtins() { return &builtins_; }
@ -55,7 +55,7 @@ class PPCFrontend {
uint32_t trace_flags, Function** out_function); uint32_t trace_flags, Function** out_function);
private: private:
Runtime* runtime_; Processor* processor_;
std::unique_ptr<ContextInfo> context_info_; std::unique_ptr<ContextInfo> context_info_;
PPCBuiltins builtins_; PPCBuiltins builtins_;
TypePool<PPCTranslator, PPCFrontend*> translator_pool_; TypePool<PPCTranslator, PPCFrontend*> translator_pool_;

View File

@ -18,7 +18,7 @@
#include "xenia/cpu/frontend/ppc_frontend.h" #include "xenia/cpu/frontend/ppc_frontend.h"
#include "xenia/cpu/frontend/ppc_instr.h" #include "xenia/cpu/frontend/ppc_instr.h"
#include "xenia/cpu/hir/label.h" #include "xenia/cpu/hir/label.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {
@ -152,9 +152,9 @@ void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
} }
FunctionInfo* PPCHIRBuilder::LookupFunction(uint32_t address) { FunctionInfo* PPCHIRBuilder::LookupFunction(uint32_t address) {
Runtime* runtime = frontend_->runtime(); Processor* processor = frontend_->processor();
FunctionInfo* symbol_info; FunctionInfo* symbol_info;
if (runtime->LookupFunctionInfo(address, &symbol_info)) { if (processor->LookupFunctionInfo(address, &symbol_info)) {
return NULL; return NULL;
} }
return symbol_info; return symbol_info;

View File

@ -16,7 +16,7 @@
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
#include "xenia/cpu/frontend/ppc_frontend.h" #include "xenia/cpu/frontend/ppc_frontend.h"
#include "xenia/cpu/frontend/ppc_instr.h" #include "xenia/cpu/frontend/ppc_instr.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
#if 0 #if 0
@ -35,7 +35,7 @@ PPCScanner::~PPCScanner() {}
bool PPCScanner::IsRestGprLr(uint32_t address) { bool PPCScanner::IsRestGprLr(uint32_t address) {
FunctionInfo* symbol_info; FunctionInfo* symbol_info;
if (frontend_->runtime()->LookupFunctionInfo(address, &symbol_info)) { if (frontend_->processor()->LookupFunctionInfo(address, &symbol_info)) {
return false; return false;
} }
return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN; return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN;

View File

@ -20,7 +20,7 @@
#include "xenia/cpu/frontend/ppc_hir_builder.h" #include "xenia/cpu/frontend/ppc_hir_builder.h"
#include "xenia/cpu/frontend/ppc_instr.h" #include "xenia/cpu/frontend/ppc_instr.h"
#include "xenia/cpu/frontend/ppc_scanner.h" #include "xenia/cpu/frontend/ppc_scanner.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {
@ -35,11 +35,11 @@ using xe::cpu::compiler::Compiler;
namespace passes = xe::cpu::compiler::passes; namespace passes = xe::cpu::compiler::passes;
PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) { PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
Backend* backend = frontend->runtime()->backend(); Backend* backend = frontend->processor()->backend();
scanner_.reset(new PPCScanner(frontend)); scanner_.reset(new PPCScanner(frontend));
builder_.reset(new PPCHIRBuilder(frontend)); builder_.reset(new PPCHIRBuilder(frontend));
compiler_.reset(new Compiler(frontend->runtime())); compiler_.reset(new Compiler(frontend->processor()));
assembler_ = std::move(backend->CreateAssembler()); assembler_ = std::move(backend->CreateAssembler());
assembler_->Initialize(); assembler_->Initialize();

View File

@ -175,30 +175,30 @@ class TestRunner {
memory.reset(new Memory()); memory.reset(new Memory());
memory->Initialize(); memory->Initialize();
runtime.reset(new Runtime(memory.get(), nullptr, 0, 0)); processor.reset(new Processor(memory.get(), nullptr));
runtime->Initialize(nullptr); processor->Setup();
} }
~TestRunner() { ~TestRunner() {
thread_state.reset(); thread_state.reset();
runtime.reset(); processor.reset();
memory.reset(); memory.reset();
} }
bool Setup(TestSuite& suite) { bool Setup(TestSuite& suite) {
// Load the binary module. // Load the binary module.
auto module = std::make_unique<xe::cpu::RawModule>(runtime.get()); auto module = std::make_unique<xe::cpu::RawModule>(processor.get());
if (module->LoadFile(START_ADDRESS, suite.bin_file_path)) { if (module->LoadFile(START_ADDRESS, suite.bin_file_path)) {
XELOGE("Unable to load test binary %ls", suite.bin_file_path.c_str()); XELOGE("Unable to load test binary %ls", suite.bin_file_path.c_str());
return false; return false;
} }
runtime->AddModule(std::move(module)); processor->AddModule(std::move(module));
// Simulate a thread. // Simulate a thread.
uint32_t stack_size = 64 * 1024; uint32_t stack_size = 64 * 1024;
uint32_t stack_address = START_ADDRESS - stack_size; uint32_t stack_address = START_ADDRESS - stack_size;
uint32_t thread_state_address = stack_address - 0x1000; uint32_t thread_state_address = stack_address - 0x1000;
thread_state.reset(new ThreadState(runtime.get(), 0x100, stack_address, thread_state.reset(new ThreadState(processor.get(), 0x100, stack_address,
stack_size, thread_state_address)); stack_size, thread_state_address));
return true; return true;
@ -213,7 +213,7 @@ class TestRunner {
// Execute test. // Execute test.
xe::cpu::Function* fn; xe::cpu::Function* fn;
runtime->ResolveFunction(test_case.address, &fn); processor->ResolveFunction(test_case.address, &fn);
if (!fn) { if (!fn) {
XELOGE("Entry function not found"); XELOGE("Entry function not found");
return false; return false;
@ -313,7 +313,7 @@ class TestRunner {
size_t memory_size; size_t memory_size;
std::unique_ptr<Memory> memory; std::unique_ptr<Memory> memory;
std::unique_ptr<Runtime> runtime; std::unique_ptr<Processor> processor;
std::unique_ptr<ThreadState> thread_state; std::unique_ptr<ThreadState> thread_state;
}; };

View File

@ -11,13 +11,15 @@
#include "xenia/memory.h" #include "xenia/memory.h"
#include "xenia/cpu/function.h" #include "xenia/cpu/function.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
Instrument::Instrument(Runtime* runtime) Instrument::Instrument(Processor* processor)
: runtime_(runtime), memory_(runtime->memory()), is_attached_(false) {} : processor_(processor),
memory_(processor->memory()),
is_attached_(false) {}
Instrument::~Instrument() { Instrument::~Instrument() {
if (is_attached_) { if (is_attached_) {
@ -43,8 +45,8 @@ bool Instrument::Detach() {
return true; return true;
} }
FunctionInstrument::FunctionInstrument(Runtime* runtime, Function* function) FunctionInstrument::FunctionInstrument(Processor* processor, Function* function)
: Instrument(runtime), target_(function) {} : Instrument(processor), target_(function) {}
bool FunctionInstrument::Attach() { bool FunctionInstrument::Attach() {
if (!Instrument::Attach()) { if (!Instrument::Attach()) {
@ -78,9 +80,9 @@ void FunctionInstrument::Exit(ThreadState* thread_state) {
// //
} }
MemoryInstrument::MemoryInstrument(Runtime* runtime, uint32_t address, MemoryInstrument::MemoryInstrument(Processor* processor, uint32_t address,
uint32_t end_address) uint32_t end_address)
: Instrument(runtime), address_(address), end_address_(end_address) {} : Instrument(processor), address_(address), end_address_(end_address) {}
bool MemoryInstrument::Attach() { bool MemoryInstrument::Attach() {
if (!Instrument::Attach()) { if (!Instrument::Attach()) {

View File

@ -12,25 +12,20 @@
#include <cstdint> #include <cstdint>
namespace xe {
namespace cpu {
class Memory;
class ThreadState;
} // namespace cpu
} // namespace xe
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Function; class Function;
class Runtime; class Memory;
class Processor;
class ThreadState;
class Instrument { class Instrument {
public: public:
Instrument(Runtime* runtime); Instrument(Processor* processor);
virtual ~Instrument(); virtual ~Instrument();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
Memory* memory() const { return memory_; } Memory* memory() const { return memory_; }
bool is_attached() const { return is_attached_; } bool is_attached() const { return is_attached_; }
@ -38,14 +33,14 @@ class Instrument {
virtual bool Detach(); virtual bool Detach();
private: private:
Runtime* runtime_; Processor* processor_;
Memory* memory_; Memory* memory_;
bool is_attached_; bool is_attached_;
}; };
class FunctionInstrument : public Instrument { class FunctionInstrument : public Instrument {
public: public:
FunctionInstrument(Runtime* runtime, Function* function); FunctionInstrument(Processor* processor, Function* function);
virtual ~FunctionInstrument() {} virtual ~FunctionInstrument() {}
Function* target() const { return target_; } Function* target() const { return target_; }
@ -86,7 +81,8 @@ class FunctionInstrument : public Instrument {
class MemoryInstrument : public Instrument { class MemoryInstrument : public Instrument {
public: public:
MemoryInstrument(Runtime* runtime, uint32_t address, uint32_t end_address); MemoryInstrument(Processor* processor, uint32_t address,
uint32_t end_address);
virtual ~MemoryInstrument() {} virtual ~MemoryInstrument() {}
uint64_t address() const { return address_; } uint64_t address() const { return address_; }

View File

@ -13,14 +13,14 @@
#include <sstream> #include <sstream>
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
Module::Module(Runtime* runtime) Module::Module(Processor* processor)
: runtime_(runtime), memory_(runtime->memory()) {} : processor_(processor), memory_(processor->memory()) {}
Module::~Module() = default; Module::~Module() = default;
@ -225,7 +225,7 @@ int Module::ReadMap(const char* file_name) {
if (type_str == "f") { if (type_str == "f") {
// Function. // Function.
FunctionInfo* fn_info; FunctionInfo* fn_info;
if (runtime_->LookupFunctionInfo(this, address, &fn_info)) { if (processor_->LookupFunctionInfo(this, address, &fn_info)) {
continue; continue;
} }
// Don't overwrite names we've set elsewhere. // Don't overwrite names we've set elsewhere.

View File

@ -23,11 +23,11 @@ namespace xe {
namespace cpu { namespace cpu {
class Function; class Function;
class Runtime; class Processor;
class Module { class Module {
public: public:
Module(Runtime* runtime); Module(Processor* processor);
virtual ~Module(); virtual ~Module();
Memory* memory() const { return memory_; } Memory* memory() const { return memory_; }
@ -57,7 +57,7 @@ class Module {
SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info); SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info);
protected: protected:
Runtime* runtime_; Processor* processor_;
Memory* memory_; Memory* memory_;
private: private:

View File

@ -9,16 +9,24 @@
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#include <gflags/gflags.h>
#include "xenia/base/assert.h"
#include "xenia/base/atomic.h" #include "xenia/base/atomic.h"
#include "xenia/base/byte_order.h" #include "xenia/base/byte_order.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
#include "xenia/cpu/cpu-private.h" #include "xenia/cpu/cpu-private.h"
#include "xenia/cpu/export_resolver.h" #include "xenia/cpu/export_resolver.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/frontend/ppc_frontend.h"
#include "xenia/cpu/module.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/cpu/xex_module.h" #include "xenia/cpu/xex_module.h"
#include "xenia/profiling.h" #include "xenia/profiling.h"
// TODO(benvanik): based on compiler support
#include "xenia/cpu/backend/x64/x64_backend.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -49,11 +57,26 @@ void InitializeIfNeeded() {
void CleanupOnShutdown() {} void CleanupOnShutdown() {}
class BuiltinModule : public Module {
public:
BuiltinModule(Processor* processor) : Module(processor), name_("builtin") {}
const std::string& name() const override { return name_; }
bool ContainsAddress(uint32_t address) override {
return (address & 0xFFFFFFF0) == 0xFFFFFFF0;
}
private:
std::string name_;
};
Processor::Processor(xe::Memory* memory, ExportResolver* export_resolver) Processor::Processor(xe::Memory* memory, ExportResolver* export_resolver)
: export_resolver_(export_resolver), : memory_(memory),
runtime_(0), debug_info_flags_(0),
memory_(memory), trace_flags_(0),
interrupt_thread_state_(NULL), builtin_module_(nullptr),
next_builtin_address_(0xFFFF0000ul),
export_resolver_(export_resolver),
interrupt_thread_state_(nullptr),
interrupt_thread_block_(0) { interrupt_thread_block_(0) {
InitializeIfNeeded(); InitializeIfNeeded();
} }
@ -64,29 +87,71 @@ Processor::~Processor() {
delete interrupt_thread_state_; delete interrupt_thread_state_;
} }
delete runtime_; {
std::lock_guard<std::mutex> guard(modules_lock_);
modules_.clear();
}
debugger_.reset();
frontend_.reset();
backend_.reset();
} }
int Processor::Setup() { int Processor::Setup() {
assert_null(runtime_); debug_info_flags_ = DEBUG_INFO_DEFAULT;
trace_flags_ = 0;
uint32_t debug_info_flags = DEBUG_INFO_DEFAULT; auto frontend = std::make_unique<xe::cpu::frontend::PPCFrontend>(this);
uint32_t trace_flags = 0; // TODO(benvanik): set options/etc.
runtime_ = // Must be initialized by subclass before calling into this.
new Runtime(memory_, export_resolver_, debug_info_flags, trace_flags); assert_not_null(memory_);
if (!runtime_) {
// Create debugger first. Other types hook up to it.
debugger_.reset(new Debugger(this));
std::unique_ptr<Module> builtin_module(new BuiltinModule(this));
builtin_module_ = builtin_module.get();
modules_.push_back(std::move(builtin_module));
if (frontend_ || backend_) {
return 1; return 1;
} }
std::unique_ptr<Backend> backend; std::unique_ptr<xe::cpu::backend::Backend> backend;
// backend.reset(new xe::cpu::backend::x64::X64Backend(runtime)); if (!backend) {
int result = runtime_->Initialize(std::move(backend)); #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND
if (FLAGS_processor_backend == "x64") {
backend.reset(new xe::cpu::backend::x64::X64Backend(this));
}
#endif // XENIA_HAS_X64_BACKEND
if (FLAGS_processor_backend == "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 1;
}
int result = backend->Initialize();
if (result) { if (result) {
return result; return result;
} }
interrupt_thread_state_ = new ThreadState(runtime_, 0, 0, 16 * 1024, 0); result = frontend->Initialize();
if (result) {
return result;
}
backend_ = std::move(backend);
frontend_ = std::move(frontend);
interrupt_thread_state_ = new ThreadState(this, 0, 0, 16 * 1024, 0);
interrupt_thread_state_->set_name("Interrupt"); interrupt_thread_state_->set_name("Interrupt");
interrupt_thread_block_ = memory_->SystemHeapAlloc(2048); interrupt_thread_block_ = memory_->SystemHeapAlloc(2048);
interrupt_thread_state_->context()->r[13] = interrupt_thread_block_; interrupt_thread_state_->context()->r[13] = interrupt_thread_block_;
@ -94,12 +159,173 @@ int Processor::Setup() {
return 0; return 0;
} }
int Processor::AddModule(std::unique_ptr<Module> module) {
std::lock_guard<std::mutex> guard(modules_lock_);
modules_.push_back(std::move(module));
return 0;
}
Module* Processor::GetModule(const char* name) {
std::lock_guard<std::mutex> guard(modules_lock_);
for (const auto& module : modules_) {
if (module->name() == name) {
return module.get();
}
}
return nullptr;
}
std::vector<Module*> Processor::GetModules() {
std::lock_guard<std::mutex> guard(modules_lock_);
std::vector<Module*> clone(modules_.size());
for (const auto& module : modules_) {
clone.push_back(module.get());
}
return clone;
}
FunctionInfo* Processor::DefineBuiltin(const std::string& name,
FunctionInfo::ExternHandler handler,
void* arg0, void* arg1) {
uint32_t address = next_builtin_address_;
next_builtin_address_ += 4;
FunctionInfo* fn_info;
builtin_module_->DeclareFunction(address, &fn_info);
fn_info->set_end_address(address + 4);
fn_info->set_name(name);
fn_info->SetupExtern(handler, arg0, arg1);
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
return fn_info;
}
std::vector<Function*> Processor::FindFunctionsWithAddress(uint32_t address) {
return entry_table_.FindWithAddress(address);
}
int Processor::ResolveFunction(uint32_t address, Function** out_function) {
*out_function = nullptr;
Entry* entry;
Entry::Status status = entry_table_.GetOrCreate(address, &entry);
if (status == Entry::STATUS_NEW) {
// Needs to be generated. We have the 'lock' on it and must do so now.
// Grab symbol declaration.
FunctionInfo* symbol_info;
int result = LookupFunctionInfo(address, &symbol_info);
if (result) {
return result;
}
result = DemandFunction(symbol_info, &entry->function);
if (result) {
entry->status = Entry::STATUS_FAILED;
return result;
}
entry->end_address = symbol_info->end_address();
status = entry->status = Entry::STATUS_READY;
}
if (status == Entry::STATUS_READY) {
// Ready to use.
*out_function = entry->function;
return 0;
} else {
// Failed or bad state.
return 1;
}
}
int Processor::LookupFunctionInfo(uint32_t address,
FunctionInfo** out_symbol_info) {
*out_symbol_info = nullptr;
// TODO(benvanik): fast reject invalid addresses/log errors.
// Find the module that contains the address.
Module* code_module = nullptr;
{
std::lock_guard<std::mutex> guard(modules_lock_);
// TODO(benvanik): sort by code address (if contiguous) so can bsearch.
// TODO(benvanik): cache last module low/high, as likely to be in there.
for (const auto& module : modules_) {
if (module->ContainsAddress(address)) {
code_module = module.get();
break;
}
}
}
if (!code_module) {
// No module found that could contain the address.
return 1;
}
return LookupFunctionInfo(code_module, address, out_symbol_info);
}
int Processor::LookupFunctionInfo(Module* module, uint32_t address,
FunctionInfo** out_symbol_info) {
// Atomic create/lookup symbol in module.
// If we get back the NEW flag we must declare it now.
FunctionInfo* symbol_info = nullptr;
SymbolInfo::Status symbol_status =
module->DeclareFunction(address, &symbol_info);
if (symbol_status == SymbolInfo::STATUS_NEW) {
// Symbol is undeclared, so declare now.
int result = frontend_->DeclareFunction(symbol_info);
if (result) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
return 1;
}
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
}
*out_symbol_info = symbol_info;
return 0;
}
int Processor::DemandFunction(FunctionInfo* symbol_info,
Function** out_function) {
*out_function = nullptr;
// Lock function for generation. If it's already being generated
// by another thread this will block and return DECLARED.
Module* module = symbol_info->module();
SymbolInfo::Status symbol_status = module->DefineFunction(symbol_info);
if (symbol_status == SymbolInfo::STATUS_NEW) {
// Symbol is undefined, so define now.
Function* function = nullptr;
int result = frontend_->DefineFunction(symbol_info, debug_info_flags_,
trace_flags_, &function);
if (result) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
return result;
}
symbol_info->set_function(function);
// Before we give the symbol back to the rest, let the debugger know.
debugger_->OnFunctionDefined(symbol_info, function);
symbol_info->set_status(SymbolInfo::STATUS_DEFINED);
symbol_status = symbol_info->status();
}
if (symbol_status == SymbolInfo::STATUS_FAILED) {
// Symbol likely failed.
return 1;
}
*out_function = symbol_info->function();
return 0;
}
int Processor::Execute(ThreadState* thread_state, uint32_t address) { int Processor::Execute(ThreadState* thread_state, uint32_t address) {
SCOPE_profile_cpu_f("cpu"); SCOPE_profile_cpu_f("cpu");
// Attempt to get the function. // Attempt to get the function.
Function* fn; Function* fn;
if (runtime_->ResolveFunction(address, &fn)) { if (ResolveFunction(address, &fn)) {
// Symbol not found in any module. // Symbol not found in any module.
XELOGCPU("Execute(%.8X): failed to find function", address); XELOGCPU("Execute(%.8X): failed to find function", address);
return 1; return 1;

View File

@ -13,7 +13,14 @@
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/debugger.h"
#include "xenia/cpu/entry_table.h"
#include "xenia/cpu/export_resolver.h" #include "xenia/cpu/export_resolver.h"
#include "xenia/cpu/frontend/ppc_frontend.h"
#include "xenia/cpu/function.h"
#include "xenia/cpu/module.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/memory.h" #include "xenia/memory.h"
namespace xe { namespace xe {
@ -35,12 +42,31 @@ class Processor {
Processor(Memory* memory, ExportResolver* export_resolver); Processor(Memory* memory, ExportResolver* export_resolver);
~Processor(); ~Processor();
ExportResolver* export_resolver() const { return export_resolver_; }
Runtime* runtime() const { return runtime_; }
Memory* memory() const { return memory_; } Memory* memory() const { return memory_; }
Debugger* debugger() const { return debugger_.get(); }
frontend::PPCFrontend* frontend() const { return frontend_.get(); }
backend::Backend* backend() const { return backend_.get(); }
ExportResolver* export_resolver() const { return export_resolver_; }
int Setup(); int Setup();
int AddModule(std::unique_ptr<Module> module);
Module* GetModule(const char* name);
Module* GetModule(const std::string& name) { return GetModule(name.c_str()); }
std::vector<Module*> GetModules();
Module* builtin_module() const { return builtin_module_; }
FunctionInfo* DefineBuiltin(const std::string& name,
FunctionInfo::ExternHandler handler, void* arg0,
void* arg1);
std::vector<Function*> FindFunctionsWithAddress(uint32_t address);
int LookupFunctionInfo(uint32_t address, FunctionInfo** out_symbol_info);
int LookupFunctionInfo(Module* module, uint32_t address,
FunctionInfo** out_symbol_info);
int ResolveFunction(uint32_t address, Function** out_function);
int Execute(ThreadState* thread_state, uint32_t address); int Execute(ThreadState* thread_state, uint32_t address);
uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t args[], uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t args[],
size_t arg_count); size_t arg_count);
@ -52,10 +78,24 @@ class Processor {
size_t arg_count); size_t arg_count);
private: private:
int DemandFunction(FunctionInfo* symbol_info, Function** out_function);
Memory* memory_;
uint32_t debug_info_flags_;
uint32_t trace_flags_;
std::unique_ptr<Debugger> debugger_;
std::unique_ptr<frontend::PPCFrontend> frontend_;
std::unique_ptr<backend::Backend> backend_;
ExportResolver* export_resolver_; ExportResolver* export_resolver_;
Runtime* runtime_; EntryTable entry_table_;
Memory* memory_; std::mutex modules_lock_;
std::vector<std::unique_ptr<Module>> modules_;
Module* builtin_module_;
uint32_t next_builtin_address_;
Irql irql_; Irql irql_;
std::mutex interrupt_thread_lock_; std::mutex interrupt_thread_lock_;

View File

@ -15,8 +15,8 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
RawModule::RawModule(Runtime* runtime) RawModule::RawModule(Processor* processor)
: Module(runtime), base_address_(0), low_address_(0), high_address_(0) {} : Module(processor), base_address_(0), low_address_(0), high_address_(0) {}
RawModule::~RawModule() {} RawModule::~RawModule() {}

View File

@ -19,7 +19,7 @@ namespace cpu {
class RawModule : public Module { class RawModule : public Module {
public: public:
RawModule(Runtime* runtime); RawModule(Processor* processor);
~RawModule() override; ~RawModule() override;
int LoadFile(uint32_t base_address, const std::wstring& path); int LoadFile(uint32_t base_address, const std::wstring& path);

View File

@ -1,274 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/cpu/runtime.h"
#include <gflags/gflags.h>
#include "xenia/base/assert.h"
#include "xenia/cpu/frontend/ppc_frontend.h"
#include "xenia/cpu/module.h"
#include "xenia/cpu/thread_state.h"
// TODO(benvanik): based on compiler support
#include "xenia/cpu/backend/x64/x64_backend.h"
DEFINE_string(runtime_backend, "any", "Runtime backend [any, x64].");
namespace xe {
namespace cpu {
class BuiltinModule : public Module {
public:
BuiltinModule(Runtime* runtime) : Module(runtime), name_("builtin") {}
const std::string& name() const override { return name_; }
bool ContainsAddress(uint32_t address) override {
return (address & 0xFFFFFFF0) == 0xFFFFFFF0;
}
private:
std::string name_;
};
Runtime::Runtime(Memory* memory, ExportResolver* export_resolver,
uint32_t debug_info_flags, uint32_t trace_flags)
: memory_(memory),
debug_info_flags_(debug_info_flags),
trace_flags_(trace_flags),
builtin_module_(nullptr),
next_builtin_address_(0xFFFF0000ul),
export_resolver_(export_resolver) {}
Runtime::~Runtime() {
{
std::lock_guard<std::mutex> guard(modules_lock_);
modules_.clear();
}
debugger_.reset();
frontend_.reset();
backend_.reset();
}
int Runtime::Initialize(std::unique_ptr<xe::cpu::backend::Backend> backend) {
auto frontend = std::make_unique<xe::cpu::frontend::PPCFrontend>(this);
// TODO(benvanik): set options/etc.
// Must be initialized by subclass before calling into this.
assert_not_null(memory_);
// Create debugger first. Other types hook up to it.
debugger_.reset(new Debugger(this));
std::unique_ptr<Module> builtin_module(new BuiltinModule(this));
builtin_module_ = builtin_module.get();
modules_.push_back(std::move(builtin_module));
if (frontend_ || backend_) {
return 1;
}
if (!backend) {
#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND
if (FLAGS_runtime_backend == "x64") {
backend.reset(new xe::cpu::backend::x64::X64Backend(this));
}
#endif // XENIA_HAS_X64_BACKEND
if (FLAGS_runtime_backend == "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 1;
}
int result = backend->Initialize();
if (result) {
return result;
}
result = frontend->Initialize();
if (result) {
return result;
}
backend_ = std::move(backend);
frontend_ = std::move(frontend);
return 0;
}
int Runtime::AddModule(std::unique_ptr<Module> module) {
std::lock_guard<std::mutex> guard(modules_lock_);
modules_.push_back(std::move(module));
return 0;
}
Module* Runtime::GetModule(const char* name) {
std::lock_guard<std::mutex> guard(modules_lock_);
for (const auto& module : modules_) {
if (module->name() == name) {
return module.get();
}
}
return nullptr;
}
std::vector<Module*> Runtime::GetModules() {
std::lock_guard<std::mutex> guard(modules_lock_);
std::vector<Module*> clone(modules_.size());
for (const auto& module : modules_) {
clone.push_back(module.get());
}
return clone;
}
FunctionInfo* Runtime::DefineBuiltin(const std::string& name,
FunctionInfo::ExternHandler handler,
void* arg0, void* arg1) {
uint32_t address = next_builtin_address_;
next_builtin_address_ += 4;
FunctionInfo* fn_info;
builtin_module_->DeclareFunction(address, &fn_info);
fn_info->set_end_address(address + 4);
fn_info->set_name(name);
fn_info->SetupExtern(handler, arg0, arg1);
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
return fn_info;
}
std::vector<Function*> Runtime::FindFunctionsWithAddress(uint32_t address) {
return entry_table_.FindWithAddress(address);
}
int Runtime::ResolveFunction(uint32_t address, Function** out_function) {
*out_function = nullptr;
Entry* entry;
Entry::Status status = entry_table_.GetOrCreate(address, &entry);
if (status == Entry::STATUS_NEW) {
// Needs to be generated. We have the 'lock' on it and must do so now.
// Grab symbol declaration.
FunctionInfo* symbol_info;
int result = LookupFunctionInfo(address, &symbol_info);
if (result) {
return result;
}
result = DemandFunction(symbol_info, &entry->function);
if (result) {
entry->status = Entry::STATUS_FAILED;
return result;
}
entry->end_address = symbol_info->end_address();
status = entry->status = Entry::STATUS_READY;
}
if (status == Entry::STATUS_READY) {
// Ready to use.
*out_function = entry->function;
return 0;
} else {
// Failed or bad state.
return 1;
}
}
int Runtime::LookupFunctionInfo(uint32_t address,
FunctionInfo** out_symbol_info) {
*out_symbol_info = nullptr;
// TODO(benvanik): fast reject invalid addresses/log errors.
// Find the module that contains the address.
Module* code_module = nullptr;
{
std::lock_guard<std::mutex> guard(modules_lock_);
// TODO(benvanik): sort by code address (if contiguous) so can bsearch.
// TODO(benvanik): cache last module low/high, as likely to be in there.
for (const auto& module : modules_) {
if (module->ContainsAddress(address)) {
code_module = module.get();
break;
}
}
}
if (!code_module) {
// No module found that could contain the address.
return 1;
}
return LookupFunctionInfo(code_module, address, out_symbol_info);
}
int Runtime::LookupFunctionInfo(Module* module, uint32_t address,
FunctionInfo** out_symbol_info) {
// Atomic create/lookup symbol in module.
// If we get back the NEW flag we must declare it now.
FunctionInfo* symbol_info = nullptr;
SymbolInfo::Status symbol_status =
module->DeclareFunction(address, &symbol_info);
if (symbol_status == SymbolInfo::STATUS_NEW) {
// Symbol is undeclared, so declare now.
int result = frontend_->DeclareFunction(symbol_info);
if (result) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
return 1;
}
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
}
*out_symbol_info = symbol_info;
return 0;
}
int Runtime::DemandFunction(FunctionInfo* symbol_info,
Function** out_function) {
*out_function = nullptr;
// Lock function for generation. If it's already being generated
// by another thread this will block and return DECLARED.
Module* module = symbol_info->module();
SymbolInfo::Status symbol_status = module->DefineFunction(symbol_info);
if (symbol_status == SymbolInfo::STATUS_NEW) {
// Symbol is undefined, so define now.
Function* function = nullptr;
int result = frontend_->DefineFunction(symbol_info, debug_info_flags_,
trace_flags_, &function);
if (result) {
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
return result;
}
symbol_info->set_function(function);
// Before we give the symbol back to the rest, let the debugger know.
debugger_->OnFunctionDefined(symbol_info, function);
symbol_info->set_status(SymbolInfo::STATUS_DEFINED);
symbol_status = symbol_info->status();
}
if (symbol_status == SymbolInfo::STATUS_FAILED) {
// Symbol likely failed.
return 1;
}
*out_function = symbol_info->function();
return 0;
}
} // namespace cpu
} // namespace xe

View File

@ -1,83 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_RUNTIME_H_
#define XENIA_CPU_RUNTIME_H_
#include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/debugger.h"
#include "xenia/cpu/entry_table.h"
#include "xenia/cpu/export_resolver.h"
#include "xenia/cpu/frontend/ppc_frontend.h"
#include "xenia/cpu/function.h"
#include "xenia/cpu/module.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/memory.h"
namespace xe {
namespace cpu {
class Runtime {
public:
Runtime(Memory* memory, ExportResolver* export_resolver,
uint32_t debug_info_flags, uint32_t trace_flags);
~Runtime();
Memory* memory() const { return memory_; }
Debugger* debugger() const { return debugger_.get(); }
frontend::PPCFrontend* frontend() const { return frontend_.get(); }
backend::Backend* backend() const { return backend_.get(); }
ExportResolver* export_resolver() const { return export_resolver_; }
int Initialize(std::unique_ptr<backend::Backend> backend = 0);
int AddModule(std::unique_ptr<Module> module);
Module* GetModule(const char* name);
Module* GetModule(const std::string& name) { return GetModule(name.c_str()); }
std::vector<Module*> GetModules();
Module* builtin_module() const { return builtin_module_; }
FunctionInfo* DefineBuiltin(const std::string& name,
FunctionInfo::ExternHandler handler, void* arg0,
void* arg1);
std::vector<Function*> FindFunctionsWithAddress(uint32_t address);
int LookupFunctionInfo(uint32_t address, FunctionInfo** out_symbol_info);
int LookupFunctionInfo(Module* module, uint32_t address,
FunctionInfo** out_symbol_info);
int ResolveFunction(uint32_t address, Function** out_function);
// uint32_t CreateCallback(void (*callback)(void* data), void* data);
private:
int DemandFunction(FunctionInfo* symbol_info, Function** out_function);
Memory* memory_;
uint32_t debug_info_flags_;
uint32_t trace_flags_;
std::unique_ptr<Debugger> debugger_;
std::unique_ptr<frontend::PPCFrontend> frontend_;
std::unique_ptr<backend::Backend> backend_;
ExportResolver* export_resolver_;
EntryTable entry_table_;
std::mutex modules_lock_;
std::vector<std::unique_ptr<Module>> modules_;
Module* builtin_module_;
uint32_t next_builtin_address_;
};
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_RUNTIME_H_

View File

@ -24,8 +24,6 @@
'processor.h', 'processor.h',
'raw_module.cc', 'raw_module.cc',
'raw_module.h', 'raw_module.h',
'runtime.cc',
'runtime.h',
'symbol_info.cc', 'symbol_info.cc',
'symbol_info.h', 'symbol_info.h',
'test_module.cc', 'test_module.cc',

View File

@ -38,44 +38,42 @@ class TestFunction {
#if XENIA_TEST_X64 #if XENIA_TEST_X64
{ {
auto runtime = std::make_unique<Runtime>(memory.get(), nullptr, 0, 0); auto processor = std::make_unique<Processor>(memory.get(), nullptr);
auto backend = processor->Setup();
std::make_unique<xe::cpu::backend::x64::X64Backend>(runtime.get()); processors.emplace_back(std::move(processor));
runtime->Initialize(std::move(backend));
runtimes.emplace_back(std::move(runtime));
} }
#endif // XENIA_TEST_X64 #endif // XENIA_TEST_X64
for (auto& runtime : runtimes) { for (auto& processor : processors) {
auto module = std::make_unique<xe::cpu::TestModule>( auto module = std::make_unique<xe::cpu::TestModule>(
runtime.get(), "Test", processor.get(), "Test",
[](uint64_t address) { return address == 0x1000; }, [](uint64_t address) { return address == 0x1000; },
[generator](hir::HIRBuilder& b) { [generator](hir::HIRBuilder& b) {
generator(b); generator(b);
return true; return true;
}); });
runtime->AddModule(std::move(module)); processor->AddModule(std::move(module));
} }
} }
~TestFunction() { ~TestFunction() {
runtimes.clear(); processors.clear();
memory.reset(); memory.reset();
} }
void Run(std::function<void(PPCContext*)> pre_call, void Run(std::function<void(PPCContext*)> pre_call,
std::function<void(PPCContext*)> post_call) { std::function<void(PPCContext*)> post_call) {
for (auto& runtime : runtimes) { for (auto& processor : processors) {
memory->Zero(0, memory_size); memory->Zero(0, memory_size);
xe::cpu::Function* fn; xe::cpu::Function* fn;
runtime->ResolveFunction(0x1000, &fn); processor->ResolveFunction(0x1000, &fn);
uint32_t stack_size = 64 * 1024; uint32_t stack_size = 64 * 1024;
uint32_t stack_address = memory_size - stack_size; uint32_t stack_address = memory_size - stack_size;
uint32_t thread_state_address = stack_address - 0x1000; uint32_t thread_state_address = stack_address - 0x1000;
auto thread_state = auto thread_state =
std::make_unique<ThreadState>(runtime.get(), 0x100, stack_address, std::make_unique<ThreadState>(processor.get(), 0x100, stack_address,
stack_size, thread_state_address); stack_size, thread_state_address);
auto ctx = thread_state->context(); auto ctx = thread_state->context();
ctx->lr = 0xBEBEBEBE; ctx->lr = 0xBEBEBEBE;
@ -90,7 +88,7 @@ class TestFunction {
uint32_t memory_size; uint32_t memory_size;
std::unique_ptr<Memory> memory; std::unique_ptr<Memory> memory;
std::vector<std::unique_ptr<Runtime>> runtimes; std::vector<std::unique_ptr<Processor>> processors;
}; };
inline hir::Value* LoadGPR(hir::HIRBuilder& b, int reg) { inline hir::Value* LoadGPR(hir::HIRBuilder& b, int reg) {

View File

@ -14,7 +14,7 @@
#include "xenia/base/reset_scope.h" #include "xenia/base/reset_scope.h"
#include "xenia/base/string.h" #include "xenia/base/string.h"
#include "xenia/cpu/compiler/compiler_passes.h" #include "xenia/cpu/compiler/compiler_passes.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -24,16 +24,16 @@ using xe::cpu::compiler::Compiler;
using xe::cpu::hir::HIRBuilder; using xe::cpu::hir::HIRBuilder;
namespace passes = xe::cpu::compiler::passes; namespace passes = xe::cpu::compiler::passes;
TestModule::TestModule(Runtime* runtime, const std::string& name, TestModule::TestModule(Processor* processor, const std::string& name,
std::function<bool(uint32_t)> contains_address, std::function<bool(uint32_t)> contains_address,
std::function<bool(hir::HIRBuilder&)> generate) std::function<bool(hir::HIRBuilder&)> generate)
: Module(runtime), : Module(processor),
name_(name), name_(name),
contains_address_(contains_address), contains_address_(contains_address),
generate_(generate) { generate_(generate) {
builder_.reset(new HIRBuilder()); builder_.reset(new HIRBuilder());
compiler_.reset(new Compiler(runtime)); compiler_.reset(new Compiler(processor));
assembler_ = std::move(runtime->backend()->CreateAssembler()); assembler_ = std::move(processor->backend()->CreateAssembler());
assembler_->Initialize(); assembler_->Initialize();
// Merge blocks early. This will let us use more context in other passes. // Merge blocks early. This will let us use more context in other passes.
@ -59,7 +59,7 @@ TestModule::TestModule(Runtime* runtime, const std::string& name,
// This should be the last pass before finalization, as after this all // This should be the last pass before finalization, as after this all
// registers are assigned and ready to be emitted. // registers are assigned and ready to be emitted.
compiler_->AddPass(std::make_unique<passes::RegisterAllocationPass>( compiler_->AddPass(std::make_unique<passes::RegisterAllocationPass>(
runtime->backend()->machine_info())); processor->backend()->machine_info()));
// Must come last. The HIR is not really HIR after this. // Must come last. The HIR is not really HIR after this.
compiler_->AddPass(std::make_unique<passes::FinalizationPass>()); compiler_->AddPass(std::make_unique<passes::FinalizationPass>());

View File

@ -24,7 +24,7 @@ namespace cpu {
class TestModule : public Module { class TestModule : public Module {
public: public:
TestModule(Runtime* runtime, const std::string& name, TestModule(Processor* processor, const std::string& name,
std::function<bool(uint32_t)> contains_address, std::function<bool(uint32_t)> contains_address,
std::function<bool(hir::HIRBuilder&)> generate); std::function<bool(hir::HIRBuilder&)> generate);
~TestModule() override; ~TestModule() override;

View File

@ -11,7 +11,7 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -22,11 +22,11 @@ using PPCContext = xe::cpu::frontend::PPCContext;
thread_local ThreadState* thread_state_ = nullptr; thread_local ThreadState* thread_state_ = nullptr;
ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id, ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
uint32_t stack_address, uint32_t stack_size, uint32_t stack_address, uint32_t stack_size,
uint32_t thread_state_address) uint32_t thread_state_address)
: runtime_(runtime), : processor_(processor),
memory_(runtime->memory()), memory_(processor->memory()),
thread_id_(thread_id), thread_id_(thread_id),
name_(""), name_(""),
backend_data_(0), backend_data_(0),
@ -38,7 +38,7 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
uint32_t system_thread_handle = xe::threading::current_thread_id(); uint32_t system_thread_handle = xe::threading::current_thread_id();
thread_id_ = 0x80000000 | system_thread_handle; thread_id_ = 0x80000000 | system_thread_handle;
} }
backend_data_ = runtime->backend()->AllocThreadData(); backend_data_ = processor->backend()->AllocThreadData();
if (!stack_address) { if (!stack_address) {
stack_address_ = memory()->SystemHeapAlloc(stack_size); stack_address_ = memory()->SystemHeapAlloc(stack_size);
@ -60,7 +60,7 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
context_->reserve_value = memory_->reserve_value(); context_->reserve_value = memory_->reserve_value();
context_->virtual_membase = memory_->virtual_membase(); context_->virtual_membase = memory_->virtual_membase();
context_->physical_membase = memory_->physical_membase(); context_->physical_membase = memory_->physical_membase();
context_->runtime = runtime; context_->processor = processor_;
context_->thread_state = this; context_->thread_state = this;
context_->thread_id = thread_id_; context_->thread_id = thread_id_;
@ -72,14 +72,14 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
// 16 to 32b. // 16 to 32b.
context_->r[1] -= 64; context_->r[1] -= 64;
runtime_->debugger()->OnThreadCreated(this); processor_->debugger()->OnThreadCreated(this);
} }
ThreadState::~ThreadState() { ThreadState::~ThreadState() {
runtime_->debugger()->OnThreadDestroyed(this); processor_->debugger()->OnThreadDestroyed(this);
if (backend_data_) { if (backend_data_) {
runtime_->backend()->FreeThreadData(backend_data_); processor_->backend()->FreeThreadData(backend_data_);
} }
if (thread_state_ == this) { if (thread_state_ == this) {
thread_state_ = nullptr; thread_state_ = nullptr;

View File

@ -17,15 +17,15 @@
namespace xe { namespace xe {
namespace cpu { namespace cpu {
class Runtime; class Processor;
class ThreadState { class ThreadState {
public: public:
ThreadState(Runtime* runtime, uint32_t thread_id, uint32_t stack_address, ThreadState(Processor* processor, uint32_t thread_id, uint32_t stack_address,
uint32_t stack_size, uint32_t thread_state_address); uint32_t stack_size, uint32_t thread_state_address);
~ThreadState(); ~ThreadState();
Runtime* runtime() const { return runtime_; } Processor* processor() const { return processor_; }
Memory* memory() const { return memory_; } Memory* memory() const { return memory_; }
uint32_t thread_id() const { return thread_id_; } uint32_t thread_id() const { return thread_id_; }
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
@ -45,7 +45,7 @@ class ThreadState {
static uint32_t GetThreadID(); static uint32_t GetThreadID();
private: private:
Runtime* runtime_; Processor* processor_;
Memory* memory_; Memory* memory_;
uint32_t thread_id_; uint32_t thread_id_;
std::string name_; std::string name_;

View File

@ -17,7 +17,7 @@
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
#include "xenia/cpu/cpu-private.h" #include "xenia/cpu/cpu-private.h"
#include "xenia/cpu/export_resolver.h" #include "xenia/cpu/export_resolver.h"
#include "xenia/cpu/runtime.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -30,9 +30,9 @@ void UndefinedImport(PPCContext* ppc_state, void* arg0, void* arg1) {
XELOGE("call to undefined kernel import"); XELOGE("call to undefined kernel import");
} }
XexModule::XexModule(Runtime* runtime) XexModule::XexModule(Processor* processor)
: Module(runtime), : Module(processor),
runtime_(runtime), processor_(processor),
xex_(nullptr), xex_(nullptr),
base_address_(0), base_address_(0),
low_address_(0), low_address_(0),
@ -93,7 +93,7 @@ int XexModule::Load(const std::string& name, const std::string& path,
} }
int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) { int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
ExportResolver* export_resolver = runtime_->export_resolver(); ExportResolver* export_resolver = processor_->export_resolver();
xe_xex2_import_info_t* import_infos; xe_xex2_import_info_t* import_infos;
size_t import_info_count; size_t import_info_count;

View File

@ -22,7 +22,7 @@ class Runtime;
class XexModule : public xe::cpu::Module { class XexModule : public xe::cpu::Module {
public: public:
XexModule(Runtime* runtime); XexModule(Processor* processor);
virtual ~XexModule(); virtual ~XexModule();
xe_xex2_ref xex() const { return xex_; } xe_xex2_ref xex() const { return xex_; }
@ -39,7 +39,7 @@ class XexModule : public xe::cpu::Module {
int FindSaveRest(); int FindSaveRest();
private: private:
Runtime* runtime_; Processor* processor_;
std::string name_; std::string name_;
std::string path_; std::string path_;
xe_xex2_ref xex_; xe_xex2_ref xex_;

View File

@ -182,7 +182,7 @@ X_STATUS XThread::Create() {
// Allocate processor thread state. // Allocate processor thread state.
// This is thread safe. // This is thread safe.
thread_state_ = thread_state_ =
new ThreadState(kernel_state()->processor()->runtime(), thread_id_, 0, new ThreadState(kernel_state()->processor(), thread_id_, 0,
creation_params_.stack_size, thread_state_address_); creation_params_.stack_size, thread_state_address_);
X_STATUS return_code = PlatformCreate(); X_STATUS return_code = PlatformCreate();

View File

@ -104,7 +104,6 @@ X_STATUS XUserModule::LoadFromFile(const char* path) {
X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) { X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
Processor* processor = kernel_state()->processor(); Processor* processor = kernel_state()->processor();
Runtime* runtime = processor->runtime();
// Load the XEX into memory and decrypt. // Load the XEX into memory and decrypt.
xe_xex2_options_t xex_options = {0}; xe_xex2_options_t xex_options = {0};
@ -130,11 +129,11 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
// Prepare the module for execution. // Prepare the module for execution.
// Runtime takes ownership. // Runtime takes ownership.
auto xex_module = std::make_unique<XexModule>(runtime); auto xex_module = std::make_unique<XexModule>(processor);
if (xex_module->Load(name_, path_, xex_)) { if (xex_module->Load(name_, path_, xex_)) {
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }
if (runtime->AddModule(std::move(xex_module))) { if (processor->AddModule(std::move(xex_module))) {
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }