From ef0032ecfff71974701fe9a233a0df94eb0a4153 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 31 May 2013 21:22:00 -0700 Subject: [PATCH] Wiring up register read/write from JIT -> GPU. --- src/xenia/cpu/jit.h | 2 + src/xenia/cpu/processor.cc | 19 ++++++++- src/xenia/cpu/processor.h | 12 +++++- src/xenia/cpu/x64/x64_emit_memory.cc | 25 +++++++++++- src/xenia/cpu/x64/x64_emitter.cc | 42 ++++++++++++++++++++ src/xenia/cpu/x64/x64_emitter.h | 9 +++++ src/xenia/cpu/x64/x64_jit.cc | 5 +++ src/xenia/cpu/x64/x64_jit.h | 2 + src/xenia/gpu/d3d11/d3d11_graphics_system.cc | 9 +++++ src/xenia/gpu/d3d11/d3d11_graphics_system.h | 3 ++ src/xenia/gpu/graphics_system.h | 12 ++++++ src/xenia/gpu/nop/nop_graphics_system.cc | 9 +++++ src/xenia/gpu/nop/nop_graphics_system.h | 3 ++ tools/xenia-run/xenia-run.cc | 24 +++++++---- 14 files changed, 164 insertions(+), 12 deletions(-) diff --git a/src/xenia/cpu/jit.h b/src/xenia/cpu/jit.h index 631f1a216..7f64532ae 100644 --- a/src/xenia/cpu/jit.h +++ b/src/xenia/cpu/jit.h @@ -30,6 +30,8 @@ public: } virtual int Setup() = 0; + virtual void SetupGpuPointers(void* gpu_this, + void* gpu_read, void* gpu_write) = 0; virtual int InitModule(ExecModule* module) = 0; virtual int UninitModule(ExecModule* module) = 0; diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 76b0a4459..8e5d52e22 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -11,6 +11,7 @@ #include #include +#include using namespace xe; @@ -66,6 +67,7 @@ Processor::~Processor() { delete jit_; delete sym_table_; + graphics_system_.reset(); export_resolver_.reset(); backend_.reset(); xe_memory_release(memory_); @@ -75,6 +77,15 @@ xe_memory_ref Processor::memory() { return xe_memory_retain(memory_); } +shared_ptr Processor::graphics_system() { + return graphics_system_; +} + +void Processor::set_graphics_system( + shared_ptr graphics_system) { + graphics_system_ = graphics_system; +} + shared_ptr Processor::export_resolver() { return export_resolver_; } @@ -95,6 +106,12 @@ int Processor::Setup() { return 1; } + XEASSERTNOTNULL(graphics_system_.get()); + jit_->SetupGpuPointers( + graphics_system_.get(), + (void*)&xe::gpu::GraphicsSystem::ReadRegisterThunk, + (void*)&xe::gpu::GraphicsSystem::WriteRegisterThunk); + return 0; } @@ -235,7 +252,7 @@ FunctionSymbol* Processor::GetFunction(uint32_t address) { return fn_symbol; } } - + // Not found at all? That seems wrong... XEASSERTALWAYS(); return NULL; diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 079e0c3e9..7034336dc 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -22,6 +22,13 @@ #include +namespace xe { +namespace gpu { +class GraphicsSystem; +} // namespace gpu +} // namespace xe + + namespace xe { namespace cpu { @@ -34,6 +41,8 @@ public: ~Processor(); xe_memory_ref memory(); + shared_ptr graphics_system(); + void set_graphics_system(shared_ptr graphics_system); shared_ptr export_resolver(); void set_export_resolver(shared_ptr export_resolver); @@ -54,7 +63,8 @@ public: private: xe_memory_ref memory_; shared_ptr backend_; - shared_ptr export_resolver_; + shared_ptr graphics_system_; + shared_ptr export_resolver_; sdb::SymbolTable* sym_table_; JIT* jit_; diff --git a/src/xenia/cpu/x64/x64_emit_memory.cc b/src/xenia/cpu/x64/x64_emit_memory.cc index e854455b2..e4528c132 100644 --- a/src/xenia/cpu/x64/x64_emit_memory.cc +++ b/src/xenia/cpu/x64/x64_emit_memory.cc @@ -10,6 +10,7 @@ #include #include +#include using namespace xe::cpu; @@ -449,9 +450,20 @@ XEEMITTER(lwz, 0x80000000, D )(X64Emitter& e, X86Compiler& c, InstrDat // EA <- b + EXTS(D) // RT <- i32.0 || MEM(EA, 4) + // Special GPU access (0x7FC8xxxx). + uint64_t constant_ea; + if (i.D.RA && e.get_constant_gpr_value(i.D.RA, &constant_ea)) { + constant_ea += XEEXTS16(i.D.DS); + if ((constant_ea & 0xFFFF0000) == 0x7FC80000) { + GpVar reg(e.read_gpu_register((uint32_t)constant_ea)); + e.update_gpr_value(i.D.RT, reg); + e.clear_constant_gpr_value(i.D.RT); + return 0; + } + } + GpVar ea(c.newGpVar()); if (i.D.RA) { - uint64_t constant_ea; if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) { constant_ea += XEEXTS16(i.D.DS); c.mov(ea, imm(constant_ea & 0xFFFFFFFF)); @@ -808,9 +820,18 @@ XEEMITTER(stw, 0x90000000, D )(X64Emitter& e, X86Compiler& c, InstrDat // EA <- b + EXTS(D) // MEM(EA, 4) <- (RS)[32:63] + // Special GPU access (0x7FC8xxxx). + uint64_t constant_ea; + if (i.D.RA && e.get_constant_gpr_value(i.D.RA, &constant_ea)) { + constant_ea += XEEXTS16(i.D.DS); + if ((constant_ea & 0xFFFF0000) == 0x7FC80000) { + e.write_gpu_register((uint32_t)constant_ea, e.gpr_value(i.D.RT)); + return 0; + } + } + GpVar ea(c.newGpVar()); if (i.D.RA) { - uint64_t constant_ea; if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) { constant_ea += XEEXTS16(i.D.DS); c.mov(ea, imm(constant_ea & 0xFFFFFFFF)); diff --git a/src/xenia/cpu/x64/x64_emitter.cc b/src/xenia/cpu/x64/x64_emitter.cc index 7f693e16c..a92c87ee2 100644 --- a/src/xenia/cpu/x64/x64_emitter.cc +++ b/src/xenia/cpu/x64/x64_emitter.cc @@ -89,6 +89,13 @@ X64Emitter::~X64Emitter() { lock_ = NULL; } +void X64Emitter::SetupGpuPointers(void* gpu_this, + void* gpu_read, void* gpu_write) { + gpu_this_ = gpu_this; + gpu_read_ = gpu_read; + gpu_write_ = gpu_write; +} + void X64Emitter::Lock() { xe_mutex_lock(lock_); } @@ -1004,6 +1011,41 @@ int X64Emitter::GenerateIndirectionBranch(uint32_t cia, GpVar& target, return 0; } +GpVar X64Emitter::read_gpu_register(uint32_t r) { + X86Compiler& c = compiler_; + + GpVar this_imm(c.newGpVar()); + c.mov(this_imm, imm((uint64_t)gpu_this_)); + GpVar reg_imm(c.newGpVar()); + c.mov(reg_imm, imm(r & 0xFFFF)); + + X86CompilerFuncCall* call = c.call(gpu_read_); + call->setPrototype(kX86FuncConvDefault, + FuncBuilder2()); + call->setArgument(0, this_imm); + call->setArgument(1, reg_imm); + GpVar res(c.newGpVar()); + call->setReturn(res); + + return res; +} + +void X64Emitter::write_gpu_register(uint32_t r, GpVar& v) { + X86Compiler& c = compiler_; + + GpVar this_imm(c.newGpVar()); + c.mov(this_imm, imm((uint64_t)gpu_this_)); + GpVar reg_imm(c.newGpVar()); + c.mov(reg_imm, imm(r & 0xFFFF)); + + X86CompilerFuncCall* call = c.call(gpu_write_); + call->setPrototype(kX86FuncConvDefault, + FuncBuilder3()); + call->setArgument(0, this_imm); + call->setArgument(1, reg_imm); + call->setArgument(2, v); +} + void X64Emitter::SetupLocals() { X86Compiler& c = compiler_; diff --git a/src/xenia/cpu/x64/x64_emitter.h b/src/xenia/cpu/x64/x64_emitter.h index 25c1116aa..9517f7858 100644 --- a/src/xenia/cpu/x64/x64_emitter.h +++ b/src/xenia/cpu/x64/x64_emitter.h @@ -31,6 +31,8 @@ public: X64Emitter(xe_memory_ref memory); ~X64Emitter(); + void SetupGpuPointers(void* gpu_this, void* gpu_read, void* gpu_write); + void Lock(); void Unlock(); @@ -55,6 +57,9 @@ public: int GenerateIndirectionBranch(uint32_t cia, AsmJit::GpVar& target, bool lk, bool likely_local); + AsmJit::GpVar read_gpu_register(uint32_t r); + void write_gpu_register(uint32_t r, AsmJit::GpVar& v); + void FillRegisters(); void SpillRegisters(); @@ -117,6 +122,10 @@ private: GlobalExports global_exports_; xe_mutex_t* lock_; + void* gpu_this_; + void* gpu_read_; + void* gpu_write_; + AsmJit::Logger* logger_; AsmJit::X86Assembler assembler_; AsmJit::X86Compiler compiler_; diff --git a/src/xenia/cpu/x64/x64_jit.cc b/src/xenia/cpu/x64/x64_jit.cc index 61b036e56..f748bb8fe 100644 --- a/src/xenia/cpu/x64/x64_jit.cc +++ b/src/xenia/cpu/x64/x64_jit.cc @@ -51,6 +51,11 @@ XECLEANUP: return result_code; } +void X64JIT::SetupGpuPointers(void* gpu_this, + void* gpu_read, void* gpu_write) { + emitter_->SetupGpuPointers(gpu_this, gpu_read, gpu_write); +} + namespace { struct BitDescription { uint32_t mask; diff --git a/src/xenia/cpu/x64/x64_jit.h b/src/xenia/cpu/x64/x64_jit.h index 16eb5e6b6..d5204e54d 100644 --- a/src/xenia/cpu/x64/x64_jit.h +++ b/src/xenia/cpu/x64/x64_jit.h @@ -29,6 +29,8 @@ public: virtual ~X64JIT(); virtual int Setup(); + virtual void SetupGpuPointers(void* gpu_this, + void* gpu_read, void* gpu_write); virtual int InitModule(ExecModule* module); virtual int UninitModule(ExecModule* module); diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_system.cc b/src/xenia/gpu/d3d11/d3d11_graphics_system.cc index 97d61fb9e..b5df269e9 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_system.cc +++ b/src/xenia/gpu/d3d11/d3d11_graphics_system.cc @@ -23,3 +23,12 @@ D3D11GraphicsSystem::D3D11GraphicsSystem(const CreationParams* params) : D3D11GraphicsSystem::~D3D11GraphicsSystem() { } + +uint64_t D3D11GraphicsSystem::ReadRegister(uint32_t r) { + XELOGGPU("ReadRegister(%.4X)", r); + return 0; +} + +void D3D11GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) { + XELOGGPU("WriteRegister(%.4X, %.8X)", r, value); +} diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_system.h b/src/xenia/gpu/d3d11/d3d11_graphics_system.h index 51f8d5687..cc7e1b4cc 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_system.h +++ b/src/xenia/gpu/d3d11/d3d11_graphics_system.h @@ -28,6 +28,9 @@ class D3D11GraphicsSystem : public GraphicsSystem { public: D3D11GraphicsSystem(const CreationParams* params); virtual ~D3D11GraphicsSystem(); + + virtual uint64_t ReadRegister(uint32_t r); + virtual void WriteRegister(uint32_t r, uint64_t value); }; diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index 652ce928c..6b2f7ae38 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -20,6 +20,8 @@ namespace gpu { class CreationParams { public: xe_memory_ref memory; + + CreationParams() : memory(NULL) {} }; @@ -29,6 +31,16 @@ public: xe_memory_ref memory(); + virtual uint64_t ReadRegister(uint32_t r) = 0; + virtual void WriteRegister(uint32_t r, uint64_t value) = 0; + + static uint64_t ReadRegisterThunk(GraphicsSystem* this_ptr, uint32_t r) { + return this_ptr->ReadRegister(r); + } + static void WriteRegisterThunk(GraphicsSystem* this_ptr, uint32_t r, uint64_t value) { + this_ptr->WriteRegister(r, value); + } + protected: GraphicsSystem(const CreationParams* params); diff --git a/src/xenia/gpu/nop/nop_graphics_system.cc b/src/xenia/gpu/nop/nop_graphics_system.cc index e4639aa26..c60d8d952 100644 --- a/src/xenia/gpu/nop/nop_graphics_system.cc +++ b/src/xenia/gpu/nop/nop_graphics_system.cc @@ -23,3 +23,12 @@ NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) : NopGraphicsSystem::~NopGraphicsSystem() { } + +uint64_t NopGraphicsSystem::ReadRegister(uint32_t r) { + XELOGGPU("ReadRegister(%.4X)", r); + return 0; +} + +void NopGraphicsSystem::WriteRegister(uint32_t r, uint64_t value) { + XELOGGPU("WriteRegister(%.4X, %.8X)", r, value); +} diff --git a/src/xenia/gpu/nop/nop_graphics_system.h b/src/xenia/gpu/nop/nop_graphics_system.h index 4c81bc630..a201555ee 100644 --- a/src/xenia/gpu/nop/nop_graphics_system.h +++ b/src/xenia/gpu/nop/nop_graphics_system.h @@ -25,6 +25,9 @@ class NopGraphicsSystem : public GraphicsSystem { public: NopGraphicsSystem(const CreationParams* params); virtual ~NopGraphicsSystem(); + + virtual uint64_t ReadRegister(uint32_t r); + virtual void WriteRegister(uint32_t r, uint64_t value); }; diff --git a/tools/xenia-run/xenia-run.cc b/tools/xenia-run/xenia-run.cc index c75894821..ce4016999 100644 --- a/tools/xenia-run/xenia-run.cc +++ b/tools/xenia-run/xenia-run.cc @@ -14,6 +14,7 @@ using namespace xe; using namespace xe::cpu; +using namespace xe::gpu; using namespace xe::dbg; using namespace xe::kernel; @@ -32,10 +33,11 @@ public: private: xe_memory_ref memory_; - shared_ptr backend_; - shared_ptr processor_; - shared_ptr runtime_; - shared_ptr debugger_; + shared_ptr backend_; + shared_ptr graphics_system_; + shared_ptr processor_; + shared_ptr runtime_; + shared_ptr debugger_; }; Run::Run() { @@ -46,20 +48,26 @@ Run::~Run() { } int Run::Setup() { + CreationParams params; + xe_pal_options_t pal_options; xe_zero_struct(&pal_options, sizeof(pal_options)); XEEXPECTZERO(xe_pal_init(pal_options)); - backend_ = shared_ptr(new xe::cpu::x64::X64Backend()); - - debugger_ = shared_ptr(new Debugger()); - xe_memory_options_t memory_options; xe_zero_struct(&memory_options, sizeof(memory_options)); memory_ = xe_memory_create(memory_options); XEEXPECTNOTNULL(memory_); + backend_ = shared_ptr(new xe::cpu::x64::X64Backend()); + + params.memory = memory_; + graphics_system_ = shared_ptr(xe::gpu::CreateNop(¶ms)); + + debugger_ = shared_ptr(new Debugger()); + processor_ = shared_ptr(new Processor(memory_, backend_)); + processor_->set_graphics_system(graphics_system_); XEEXPECTZERO(processor_->Setup()); runtime_ = shared_ptr(new Runtime(processor_, XT("")));