Massive refactoring of all code + audio skeleton.

This should make it easier to find files and (in the future) split things
up into separate libraries.
It also changes around emulator initialization to make it a little more
difficult to do things out of order and a little more sensible as to when
real init work happens.
Also adding a skeleton audio system/driver and reworking CPU register
access to be more extensible.
This commit is contained in:
Ben Vanik
2013-10-23 20:42:24 -07:00
parent c996a4bbaf
commit b7ffd46319
182 changed files with 3919 additions and 3286 deletions

View File

@@ -12,7 +12,7 @@
#include <xenia/common.h>
#include <xenia/core/memory.h>
#include <xenia/memory.h>
namespace xe {

View File

@@ -16,11 +16,10 @@
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
ExecModule::ExecModule(
xe_memory_ref memory, shared_ptr<ExportResolver> export_resolver,
xe_memory_ref memory, ExportResolver* export_resolver,
SymbolTable* sym_table,
const char* module_name, const char* module_path) {
memory_ = xe_memory_retain(memory);
@@ -42,7 +41,7 @@ SymbolDatabase* ExecModule::sdb() {
int ExecModule::PrepareRawBinary(uint32_t start_address, uint32_t end_address) {
sdb_ = shared_ptr<sdb::SymbolDatabase>(
new sdb::RawSymbolDatabase(memory_, export_resolver_.get(),
new sdb::RawSymbolDatabase(memory_, export_resolver_,
sym_table_, start_address, end_address));
code_addr_low_ = start_address;
@@ -53,7 +52,7 @@ int ExecModule::PrepareRawBinary(uint32_t start_address, uint32_t end_address) {
int ExecModule::PrepareXexModule(xe_xex2_ref xex) {
sdb_ = shared_ptr<sdb::SymbolDatabase>(
new sdb::XexSymbolDatabase(memory_, export_resolver_.get(),
new sdb::XexSymbolDatabase(memory_, export_resolver_,
sym_table_, xex));
code_addr_low_ = UINT_MAX;

View File

@@ -13,8 +13,8 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/export_resolver.h>
#include <xenia/cpu/sdb.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/xex2.h>
@@ -25,7 +25,7 @@ namespace cpu {
class ExecModule {
public:
ExecModule(
xe_memory_ref memory, shared_ptr<kernel::ExportResolver> export_resolver,
xe_memory_ref memory, ExportResolver* export_resolver,
sdb::SymbolTable* sym_table,
const char* module_name, const char* module_path);
~ExecModule();
@@ -43,11 +43,11 @@ private:
int Prepare();
int Init();
xe_memory_ref memory_;
shared_ptr<kernel::ExportResolver> export_resolver_;
sdb::SymbolTable* sym_table_;
char* module_name_;
char* module_path_;
xe_memory_ref memory_;
ExportResolver* export_resolver_;
sdb::SymbolTable* sym_table_;
char* module_name_;
char* module_path_;
shared_ptr<sdb::SymbolDatabase> sdb_;
uint32_t code_addr_low_;

View File

@@ -15,13 +15,12 @@
#include <xenia/cpu/sdb.h>
#include <xenia/cpu/ppc/instr.h>
#include <xenia/cpu/ppc/state.h>
#include <xenia/kernel/export.h>
#include <xenia/export_resolver.h>
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
namespace {

View File

@@ -13,9 +13,9 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/export_resolver.h>
#include <xenia/cpu/ppc/state.h>
#include <xenia/cpu/sdb/symbol.h>
#include <xenia/kernel/export.h>
namespace xe {
@@ -33,7 +33,7 @@ typedef struct {
xe_ppc_state_t* state, uint64_t cia, uint64_t ea);
void (_cdecl *XeTraceKernelCall)(
xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia,
kernel::KernelExport* kernel_export);
KernelExport* kernel_export);
void (_cdecl *XeTraceUserCall)(
xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia,
sdb::FunctionSymbol* fn);

View File

@@ -30,8 +30,8 @@ public:
}
virtual int Setup() = 0;
virtual void SetupGpuPointers(void* gpu_this,
void* gpu_read, void* gpu_write) = 0;
virtual void AddRegisterAccessCallbacks(
ppc::RegisterAccessCallbacks callbacks) = 0;
virtual int InitModule(ExecModule* module) = 0;
virtual int UninitModule(ExecModule* module) = 0;

View File

@@ -13,6 +13,7 @@
#include <xenia/common.h>
#include <xenia/cpu/ppc/instr.h>
#include <xenia/cpu/ppc/registers.h>
#include <xenia/cpu/ppc/state.h>
#endif // XENIA_CPU_PPC_H_

View File

@@ -0,0 +1,40 @@
/**
******************************************************************************
* 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_PPC_REGISTERS_H_
#define XENIA_CPU_PPC_REGISTERS_H_
#include <xenia/common.h>
namespace xe {
namespace cpu {
namespace ppc {
typedef bool (*RegisterHandlesCallback)(void* context, uint32_t addr);
typedef uint64_t (*RegisterReadCallback)(void* context, uint32_t addr);
typedef void (*RegisterWriteCallback)(void* context, uint32_t addr,
uint64_t value);
typedef struct {
void* context;
RegisterHandlesCallback handles;
RegisterReadCallback read;
RegisterWriteCallback write;
} RegisterAccessCallbacks;
} // namespace ppc
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_PPC_REGISTERS_H_

View File

@@ -10,6 +10,7 @@
'instr.cc',
'instr.h',
'instr_tables.h',
'registers.h',
'state.cc',
'state.h',
],

View File

@@ -13,12 +13,8 @@
#include <stdint.h>
namespace xe {
namespace cpu {
class Processor;
class ThreadState;
} // namespace cpu
} // namespace xe
XEDECLARECLASS2(xe, cpu, Processor);
XEDECLARECLASS2(xe, cpu, ThreadState);
// namespace FPRF {

View File

@@ -9,16 +9,15 @@
#include <xenia/cpu/processor.h>
#include <xenia/emulator.h>
#include <xenia/cpu/jit.h>
#include <xenia/cpu/ppc/disasm.h>
#include <xenia/cpu/ppc/state.h>
#include <xenia/gpu/graphics_system.h>
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
namespace {
@@ -46,11 +45,14 @@ namespace {
}
Processor::Processor(xe_memory_ref memory, shared_ptr<Backend> backend) :
Processor::Processor(Emulator* emulator, Backend* backend) :
sym_table_(NULL), jit_(NULL),
interrupt_thread_lock_(NULL), interrupt_thread_state_(NULL) {
memory_ = xe_memory_retain(memory);
emulator_ = emulator;
backend_ = backend;
memory_ = xe_memory_retain(emulator->memory());
export_resolver_ = emulator->export_resolver();
sym_lock_ = xe_mutex_alloc(10000);
InitializeIfNeeded();
@@ -76,34 +78,9 @@ Processor::~Processor() {
delete sym_table_;
xe_mutex_free(sym_lock_);
graphics_system_.reset();
export_resolver_.reset();
backend_.reset();
xe_memory_release(memory_);
}
xe_memory_ref Processor::memory() {
return xe_memory_retain(memory_);
}
shared_ptr<gpu::GraphicsSystem> Processor::graphics_system() {
return graphics_system_;
}
void Processor::set_graphics_system(
shared_ptr<gpu::GraphicsSystem> graphics_system) {
graphics_system_ = graphics_system;
}
shared_ptr<ExportResolver> Processor::export_resolver() {
return export_resolver_;
}
void Processor::set_export_resolver(
shared_ptr<ExportResolver> export_resolver) {
export_resolver_ = export_resolver;
}
int Processor::Setup() {
XEASSERTNULL(jit_);
@@ -121,15 +98,15 @@ 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;
}
void Processor::AddRegisterAccessCallbacks(
ppc::RegisterAccessCallbacks callbacks) {
XEASSERTNOTNULL(jit_);
jit_->AddRegisterAccessCallbacks(callbacks);
}
int Processor::LoadRawBinary(const xechar_t* path, uint32_t start_address) {
ExecModule* exec_module = NULL;
const xechar_t* name = xestrrchr(path, XE_PATH_SEPARATOR) + 1;

View File

@@ -18,15 +18,10 @@
#include <xenia/cpu/exec_module.h>
#include <xenia/cpu/thread_state.h>
#include <xenia/cpu/sdb/symbol_table.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/xex2.h>
namespace xe {
namespace gpu {
class GraphicsSystem;
} // namespace gpu
} // namespace xe
XEDECLARECLASS1(xe, Emulator);
XEDECLARECLASS1(xe, ExportResolver);
namespace xe {
@@ -37,17 +32,16 @@ class JIT;
class Processor {
public:
Processor(xe_memory_ref memory, shared_ptr<Backend> backend);
Processor(Emulator* emulator, Backend* backend);
~Processor();
xe_memory_ref memory();
shared_ptr<gpu::GraphicsSystem> graphics_system();
void set_graphics_system(shared_ptr<gpu::GraphicsSystem> graphics_system);
shared_ptr<kernel::ExportResolver> export_resolver();
void set_export_resolver(shared_ptr<kernel::ExportResolver> export_resolver);
xe_memory_ref memory() const { return memory_; }
ExportResolver* export_resolver() const { return export_resolver_; }
int Setup();
void AddRegisterAccessCallbacks(ppc::RegisterAccessCallbacks callbacks);
int LoadRawBinary(const xechar_t* path, uint32_t start_address);
int LoadXexModule(const char* name, const char* path, xe_xex2_ref xex);
@@ -69,19 +63,19 @@ public:
void* GetFunctionPointer(uint32_t address);
private:
xe_memory_ref memory_;
shared_ptr<Backend> backend_;
shared_ptr<gpu::GraphicsSystem> graphics_system_;
shared_ptr<kernel::ExportResolver> export_resolver_;
Emulator* emulator_;
Backend* backend_;
xe_memory_ref memory_;
ExportResolver* export_resolver_;
sdb::SymbolTable* sym_table_;
JIT* jit_;
sdb::SymbolTable* sym_table_;
JIT* jit_;
std::vector<ExecModule*> modules_;
xe_mutex_t* sym_lock_;
xe_mutex_t* sym_lock_;
xe_mutex_t* interrupt_thread_lock_;
ThreadState* interrupt_thread_state_;
uint32_t interrupt_thread_block_;
xe_mutex_t* interrupt_thread_lock_;
ThreadState* interrupt_thread_state_;
uint32_t interrupt_thread_block_;
};

View File

@@ -17,7 +17,6 @@ using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::ppc;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
RawSymbolDatabase::RawSymbolDatabase(

View File

@@ -21,7 +21,7 @@ namespace sdb {
class RawSymbolDatabase : public SymbolDatabase {
public:
RawSymbolDatabase(xe_memory_ref memory,
kernel::ExportResolver* export_resolver,
ExportResolver* export_resolver,
SymbolTable* sym_table,
uint32_t start_address, uint32_t end_address);
virtual ~RawSymbolDatabase();

View File

@@ -17,7 +17,6 @@ using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::ppc;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
Symbol::Symbol(SymbolType type) :

View File

@@ -15,7 +15,7 @@
#include <map>
#include <vector>
#include <xenia/kernel/export.h>
#include <xenia/export_resolver.h>
namespace xe {
@@ -125,7 +125,7 @@ public:
FunctionType type;
uint32_t flags;
kernel::KernelExport* kernel_export;
KernelExport* kernel_export;
ExceptionEntrySymbol* ee;
// Implementation-specific value. This could be a JIT'ed function ref
@@ -147,9 +147,9 @@ public:
VariableSymbol();
virtual ~VariableSymbol();
uint32_t address;
uint32_t address;
kernel::KernelExport* kernel_export;
KernelExport* kernel_export;
};
class ExceptionEntrySymbol : public Symbol {

View File

@@ -20,12 +20,12 @@ using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::ppc;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
SymbolDatabase::SymbolDatabase(xe_memory_ref memory,
ExportResolver* export_resolver,
SymbolTable* sym_table) {
SymbolTable* sym_table) :
function_count_(0), variable_count_(0) {
memory_ = xe_memory_retain(memory);
export_resolver_ = export_resolver;
sym_table_ = sym_table;

View File

@@ -16,7 +16,7 @@
#include <map>
#include <vector>
#include <xenia/kernel/export.h>
#include <xenia/export_resolver.h>
#include <xenia/cpu/sdb/symbol.h>
#include <xenia/cpu/sdb/symbol_table.h>
@@ -28,7 +28,7 @@ namespace sdb {
class SymbolDatabase {
public:
SymbolDatabase(xe_memory_ref memory, kernel::ExportResolver* export_resolver,
SymbolDatabase(xe_memory_ref memory, ExportResolver* export_resolver,
SymbolTable* sym_table);
virtual ~SymbolDatabase();
@@ -64,7 +64,7 @@ protected:
virtual bool IsValueInTextRange(uint32_t value) = 0;
xe_memory_ref memory_;
kernel::ExportResolver* export_resolver_;
ExportResolver* export_resolver_;
SymbolTable* sym_table_;
size_t function_count_;
size_t variable_count_;

View File

@@ -17,7 +17,6 @@ using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::ppc;
using namespace xe::cpu::sdb;
using namespace xe::kernel;
namespace {

View File

@@ -23,7 +23,7 @@ namespace sdb {
class XexSymbolDatabase : public SymbolDatabase {
public:
XexSymbolDatabase(xe_memory_ref memory,
kernel::ExportResolver* export_resolver,
ExportResolver* export_resolver,
SymbolTable* sym_table, xe_xex2_ref xex);
virtual ~XexSymbolDatabase();

View File

@@ -9,7 +9,7 @@
#include <xenia/cpu/thread_state.h>
#include <xenia/core/memory.h>
#include <xenia/memory.h>
#include <xenia/cpu/processor.h>

View File

@@ -454,8 +454,8 @@ XEEMITTER(lwz, 0x80000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
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));
GpVar reg;
if (e.check_constant_gpr_read((uint32_t)constant_ea, &reg)) {
e.update_gpr_value(i.D.RT, reg);
e.clear_constant_gpr_value(i.D.RT);
return 0;
@@ -824,8 +824,7 @@ XEEMITTER(stw, 0x90000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
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));
if (e.check_constant_gpr_write((uint32_t)constant_ea, e.gpr_value(i.D.RT))) {
return 0;
}
}

View File

@@ -94,11 +94,9 @@ 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::AddRegisterAccessCallbacks(
RegisterAccessCallbacks callbacks) {
access_callbacks_.push_back(callbacks);
}
void X64Emitter::Lock() {
@@ -1155,44 +1153,6 @@ 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<uint64_t, void*, uint32_t>());
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.alloc(this_imm, rcx);
c.mov(this_imm, imm((uint64_t)gpu_this_));
GpVar reg_imm(c.newGpVar());
c.alloc(reg_imm, rdx);
c.mov(reg_imm, imm(r & 0xFFFF));
c.alloc(v, r8);
X86CompilerFuncCall* call = c.call(gpu_write_);
call->setPrototype(kX86FuncConvDefault,
FuncBuilder3<void, void*, uint32_t, uint64_t>());
call->setArgument(0, this_imm);
call->setArgument(1, reg_imm);
call->setArgument(2, v);
}
void X64Emitter::SetupLocals() {
X86Compiler& c = compiler_;
@@ -1505,6 +1465,69 @@ void X64Emitter::clear_all_constant_gpr_values() {
}
}
bool X64Emitter::check_constant_gpr_read(uint32_t addr, GpVar* reg) {
X86Compiler& c = compiler_;
for (std::vector<RegisterAccessCallbacks>::const_iterator it =
access_callbacks_.begin(); it != access_callbacks_.end(); ++it) {
if (!it->handles(it->context, addr)) {
continue;
}
GpVar this_imm(c.newGpVar());
c.mov(this_imm, imm((uint64_t)it->context));
GpVar reg_imm(c.newGpVar());
c.mov(reg_imm, imm(addr));
X86CompilerFuncCall* call = c.call(it->read);
call->setPrototype(
kX86FuncConvDefault,
FuncBuilder2<uint64_t, void*, uint32_t>());
call->setArgument(0, this_imm);
call->setArgument(1, reg_imm);
GpVar res(c.newGpVar());
call->setReturn(res);
*reg = res;
// Don't let the caller handle the write.
return true;
}
return false;
}
bool X64Emitter::check_constant_gpr_write(uint32_t addr, GpVar& reg) {
X86Compiler& c = compiler_;
for (std::vector<RegisterAccessCallbacks>::const_iterator it =
access_callbacks_.begin(); it != access_callbacks_.end(); ++it) {
if (!it->handles(it->context, addr)) {
continue;
}
GpVar this_imm(c.newGpVar());
c.alloc(this_imm, rcx);
c.mov(this_imm, imm((uint64_t)it->context));
GpVar reg_imm(c.newGpVar());
c.alloc(reg_imm, rdx);
c.mov(reg_imm, imm(addr));
c.alloc(reg, r8);
X86CompilerFuncCall* call = c.call(it->write);
call->setPrototype(
kX86FuncConvDefault,
FuncBuilder3<void, void*, uint32_t, uint64_t>());
call->setArgument(0, this_imm);
call->setArgument(1, reg_imm);
call->setArgument(2, reg);
// Don't let the caller handle the write.
return true;
}
return false;
}
GpVar X64Emitter::xer_value() {
X86Compiler& c = compiler_;
if (FLAGS_cache_registers) {

View File

@@ -11,8 +11,8 @@
#define XENIA_CPU_X64_X64_EMITTER_H_
#include <xenia/cpu/global_exports.h>
#include <xenia/cpu/ppc.h>
#include <xenia/cpu/sdb.h>
#include <xenia/cpu/ppc/instr.h>
#include <asmjit/asmjit.h>
@@ -31,7 +31,7 @@ public:
X64Emitter(xe_memory_ref memory);
~X64Emitter();
void SetupGpuPointers(void* gpu_this, void* gpu_read, void* gpu_write);
void AddRegisterAccessCallbacks(ppc::RegisterAccessCallbacks callbacks);
void Lock();
void Unlock();
@@ -75,6 +75,9 @@ public:
void clear_constant_gpr_value(uint32_t n);
void clear_all_constant_gpr_values();
bool check_constant_gpr_read(uint32_t addr, AsmJit::GpVar* reg);
bool check_constant_gpr_write(uint32_t addr, AsmJit::GpVar& reg);
AsmJit::GpVar xer_value();
void update_xer_value(AsmJit::GpVar& value);
void update_xer_with_overflow(AsmJit::GpVar& value);
@@ -139,9 +142,7 @@ private:
xe_mutex_t* lock_;
uint32_t cpu_feature_mask_;
void* gpu_this_;
void* gpu_read_;
void* gpu_write_;
std::vector<ppc::RegisterAccessCallbacks> access_callbacks_;
static uint64_t reserved_addr_;

View File

@@ -18,6 +18,7 @@
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::ppc;
using namespace xe::cpu::sdb;
using namespace xe::cpu::x64;
@@ -53,9 +54,8 @@ XECLEANUP:
return result_code;
}
void X64JIT::SetupGpuPointers(void* gpu_this,
void* gpu_read, void* gpu_write) {
emitter_->SetupGpuPointers(gpu_this, gpu_read, gpu_write);
void X64JIT::AddRegisterAccessCallbacks(RegisterAccessCallbacks callbacks) {
emitter_->AddRegisterAccessCallbacks(callbacks);
}
namespace {

View File

@@ -29,8 +29,8 @@ public:
virtual ~X64JIT();
virtual int Setup();
virtual void SetupGpuPointers(void* gpu_this,
void* gpu_read, void* gpu_write);
virtual void AddRegisterAccessCallbacks(
ppc::RegisterAccessCallbacks callbacks);
virtual int InitModule(ExecModule* module);
virtual int UninitModule(ExecModule* module);