Kernel calls and variables now working and tracing better.
This commit is contained in:
parent
5c2060af72
commit
6c4af5aa70
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class DIBuilder;
|
class DIBuilder;
|
||||||
|
class ExecutionEngine;
|
||||||
class Function;
|
class Function;
|
||||||
class FunctionType;
|
class FunctionType;
|
||||||
class LLVMContext;
|
class LLVMContext;
|
||||||
|
@ -42,7 +43,8 @@ public:
|
||||||
xe_memory_ref memory, kernel::ExportResolver* export_resolver,
|
xe_memory_ref memory, kernel::ExportResolver* export_resolver,
|
||||||
const char* module_name, const char* module_path,
|
const char* module_name, const char* module_path,
|
||||||
sdb::SymbolDatabase* sdb,
|
sdb::SymbolDatabase* sdb,
|
||||||
llvm::LLVMContext* context, llvm::Module* gen_module);
|
llvm::LLVMContext* context, llvm::Module* gen_module,
|
||||||
|
llvm::ExecutionEngine* engine);
|
||||||
~ModuleGenerator();
|
~ModuleGenerator();
|
||||||
|
|
||||||
int Generate();
|
int Generate();
|
||||||
|
@ -76,6 +78,7 @@ private:
|
||||||
|
|
||||||
llvm::LLVMContext* context_;
|
llvm::LLVMContext* context_;
|
||||||
llvm::Module* gen_module_;
|
llvm::Module* gen_module_;
|
||||||
|
llvm::ExecutionEngine* engine_;
|
||||||
llvm::DIBuilder* di_builder_;
|
llvm::DIBuilder* di_builder_;
|
||||||
llvm::MDNode* cu_;
|
llvm::MDNode* cu_;
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,7 @@ typedef struct XECACHEALIGN64 xe_ppc_state {
|
||||||
|
|
||||||
// Runtime-specific data pointer. Used on callbacks to get access to the
|
// Runtime-specific data pointer. Used on callbacks to get access to the
|
||||||
// current runtime and its data.
|
// current runtime and its data.
|
||||||
|
uint8_t* membase;
|
||||||
void* processor;
|
void* processor;
|
||||||
void* thread_state;
|
void* thread_state;
|
||||||
void* runtime;
|
void* runtime;
|
||||||
|
|
|
@ -33,6 +33,7 @@ public:
|
||||||
private:
|
private:
|
||||||
uint32_t stack_address_;
|
uint32_t stack_address_;
|
||||||
uint32_t stack_size_;
|
uint32_t stack_size_;
|
||||||
|
xe_memory_ref memory_;
|
||||||
|
|
||||||
xe_ppc_state_t ppc_state_;
|
xe_ppc_state_t ppc_state_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace kernel {
|
||||||
|
|
||||||
|
|
||||||
typedef void (*xe_kernel_export_impl_fn)();
|
typedef void (*xe_kernel_export_impl_fn)();
|
||||||
typedef void (*xe_kernel_export_shim_fn)(xe_ppc_state_t* state);
|
typedef void (*xe_kernel_export_shim_fn)(xe_ppc_state_t*, void*);
|
||||||
|
|
||||||
class KernelExport {
|
class KernelExport {
|
||||||
public:
|
public:
|
||||||
|
@ -47,6 +47,9 @@ public:
|
||||||
uint32_t variable_ptr;
|
uint32_t variable_ptr;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
// Second argument passed to the shim function.
|
||||||
|
void* shim_data;
|
||||||
|
|
||||||
// Shimmed implementation.
|
// Shimmed implementation.
|
||||||
// This is called directly from generated code.
|
// This is called directly from generated code.
|
||||||
// It should parse args, do fixups, and call the impl.
|
// It should parse args, do fixups, and call the impl.
|
||||||
|
@ -83,7 +86,7 @@ public:
|
||||||
void SetVariableMapping(const char* library_name, const uint32_t ordinal,
|
void SetVariableMapping(const char* library_name, const uint32_t ordinal,
|
||||||
uint32_t value);
|
uint32_t value);
|
||||||
void SetFunctionMapping(const char* library_name, const uint32_t ordinal,
|
void SetFunctionMapping(const char* library_name, const uint32_t ordinal,
|
||||||
xe_kernel_export_shim_fn shim,
|
void* shim_data, xe_kernel_export_shim_fn shim,
|
||||||
xe_kernel_export_impl_fn impl);
|
xe_kernel_export_impl_fn impl);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -117,23 +117,26 @@ void FunctionGenerator::PopInsertPoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::GenerateBasicBlocks() {
|
void FunctionGenerator::GenerateBasicBlocks() {
|
||||||
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
// Always add an entry block.
|
// Always add an entry block.
|
||||||
BasicBlock* entry = BasicBlock::Create(*context_, "entry", gen_fn_);
|
BasicBlock* entry = BasicBlock::Create(*context_, "entry", gen_fn_);
|
||||||
builder_->SetInsertPoint(entry);
|
b.SetInsertPoint(entry);
|
||||||
|
|
||||||
if (FLAGS_trace_user_calls) {
|
if (FLAGS_trace_user_calls) {
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
Value* traceUserCall = gen_module_->getFunction("XeTraceUserCall");
|
Value* traceUserCall = gen_module_->getFunction("XeTraceUserCall");
|
||||||
builder_->CreateCall3(
|
b.CreateCall4(
|
||||||
traceUserCall,
|
traceUserCall,
|
||||||
gen_fn_->arg_begin(),
|
gen_fn_->arg_begin(),
|
||||||
builder_->getInt64(fn_->start_address),
|
b.getInt64(fn_->start_address),
|
||||||
++gen_fn_->arg_begin());
|
++gen_fn_->arg_begin(),
|
||||||
|
b.getInt64((uint64_t)fn_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this function is empty, abort!
|
// If this function is empty, abort!
|
||||||
if (!fn_->blocks.size()) {
|
if (!fn_->blocks.size()) {
|
||||||
builder_->CreateRetVoid();
|
b.CreateRetVoid();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,13 +217,15 @@ void FunctionGenerator::GenerateSharedBlocks() {
|
||||||
|
|
||||||
void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||||
BasicBlock* bb) {
|
BasicBlock* bb) {
|
||||||
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address);
|
printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address);
|
||||||
|
|
||||||
fn_block_ = block;
|
fn_block_ = block;
|
||||||
bb_ = bb;
|
bb_ = bb;
|
||||||
|
|
||||||
// Move the builder to this block and setup.
|
// Move the builder to this block and setup.
|
||||||
builder_->SetInsertPoint(bb);
|
b.SetInsertPoint(bb);
|
||||||
//i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname)));
|
//i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname)));
|
||||||
|
|
||||||
Value* invalidInstruction =
|
Value* invalidInstruction =
|
||||||
|
@ -238,21 +243,21 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||||
|
|
||||||
if (FLAGS_trace_instructions) {
|
if (FLAGS_trace_instructions) {
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
builder_->CreateCall3(
|
b.CreateCall3(
|
||||||
traceInstruction,
|
traceInstruction,
|
||||||
gen_fn_->arg_begin(),
|
gen_fn_->arg_begin(),
|
||||||
builder_->getInt32(i.address),
|
b.getInt32(i.address),
|
||||||
builder_->getInt32(i.code));
|
b.getInt32(i.code));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!i.type) {
|
if (!i.type) {
|
||||||
XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code);
|
XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code);
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
builder_->CreateCall3(
|
b.CreateCall3(
|
||||||
invalidInstruction,
|
invalidInstruction,
|
||||||
gen_fn_->arg_begin(),
|
gen_fn_->arg_begin(),
|
||||||
builder_->getInt32(i.address),
|
b.getInt32(i.address),
|
||||||
builder_->getInt32(i.code));
|
b.getInt32(i.code));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printf(" %.8X: %.8X %s\n", ia, i.code, i.type->name);
|
printf(" %.8X: %.8X %s\n", ia, i.code, i.type->name);
|
||||||
|
@ -273,11 +278,11 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||||
XELOGCPU("Unimplemented instr %.8X %.8X %s",
|
XELOGCPU("Unimplemented instr %.8X %.8X %s",
|
||||||
ia, i.code, i.type->name);
|
ia, i.code, i.type->name);
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
builder_->CreateCall3(
|
b.CreateCall3(
|
||||||
invalidInstruction,
|
invalidInstruction,
|
||||||
gen_fn_->arg_begin(),
|
gen_fn_->arg_begin(),
|
||||||
builder_->getInt32(i.address),
|
b.getInt32(i.address),
|
||||||
builder_->getInt32(i.code));
|
b.getInt32(i.code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,13 +290,13 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||||
if (block->outgoing_type == FunctionBlock::kTargetNone) {
|
if (block->outgoing_type == FunctionBlock::kTargetNone) {
|
||||||
BasicBlock* next_bb = GetNextBasicBlock();
|
BasicBlock* next_bb = GetNextBasicBlock();
|
||||||
XEASSERTNOTNULL(next_bb);
|
XEASSERTNOTNULL(next_bb);
|
||||||
builder_->CreateBr(next_bb);
|
b.CreateBr(next_bb);
|
||||||
} else if (block->outgoing_type == FunctionBlock::kTargetUnknown) {
|
} else if (block->outgoing_type == FunctionBlock::kTargetUnknown) {
|
||||||
// Hrm.
|
// Hrm.
|
||||||
// TODO(benvanik): assert this doesn't occur - means a bad sdb run!
|
// TODO(benvanik): assert this doesn't occur - means a bad sdb run!
|
||||||
XELOGCPU("SDB function scan error in %.8X: bb %.8X has unknown exit\n",
|
XELOGCPU("SDB function scan error in %.8X: bb %.8X has unknown exit\n",
|
||||||
fn_->start_address, block->start_address);
|
fn_->start_address, block->start_address);
|
||||||
builder_->CreateRetVoid();
|
b.CreateRetVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(benvanik): finish up BB
|
// TODO(benvanik): finish up BB
|
||||||
|
@ -348,7 +353,7 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target,
|
||||||
// after we are done with all user instructions.
|
// after we are done with all user instructions.
|
||||||
if (!external_indirection_block_) {
|
if (!external_indirection_block_) {
|
||||||
// Setup locals in the entry block.
|
// Setup locals in the entry block.
|
||||||
builder_->SetInsertPoint(&gen_fn_->getEntryBlock());
|
b.SetInsertPoint(&gen_fn_->getEntryBlock());
|
||||||
locals_.indirection_target = b.CreateAlloca(
|
locals_.indirection_target = b.CreateAlloca(
|
||||||
b.getInt64Ty(), 0, "indirection_target");
|
b.getInt64Ty(), 0, "indirection_target");
|
||||||
locals_.indirection_cia = b.CreateAlloca(
|
locals_.indirection_cia = b.CreateAlloca(
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <llvm/PassManager.h>
|
#include <llvm/PassManager.h>
|
||||||
#include <llvm/DebugInfo.h>
|
#include <llvm/DebugInfo.h>
|
||||||
#include <llvm/Analysis/Verifier.h>
|
#include <llvm/Analysis/Verifier.h>
|
||||||
|
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||||
#include <llvm/IR/Attributes.h>
|
#include <llvm/IR/Attributes.h>
|
||||||
#include <llvm/IR/DataLayout.h>
|
#include <llvm/IR/DataLayout.h>
|
||||||
#include <llvm/IR/DerivedTypes.h>
|
#include <llvm/IR/DerivedTypes.h>
|
||||||
|
@ -40,7 +41,7 @@ using namespace xe::kernel;
|
||||||
ModuleGenerator::ModuleGenerator(
|
ModuleGenerator::ModuleGenerator(
|
||||||
xe_memory_ref memory, ExportResolver* export_resolver,
|
xe_memory_ref memory, ExportResolver* export_resolver,
|
||||||
const char* module_name, const char* module_path, SymbolDatabase* sdb,
|
const char* module_name, const char* module_path, SymbolDatabase* sdb,
|
||||||
LLVMContext* context, Module* gen_module) {
|
LLVMContext* context, Module* gen_module, ExecutionEngine* engine) {
|
||||||
memory_ = xe_memory_retain(memory);
|
memory_ = xe_memory_retain(memory);
|
||||||
export_resolver_ = export_resolver;
|
export_resolver_ = export_resolver;
|
||||||
module_name_ = xestrdupa(module_name);
|
module_name_ = xestrdupa(module_name);
|
||||||
|
@ -48,6 +49,7 @@ ModuleGenerator::ModuleGenerator(
|
||||||
sdb_ = sdb;
|
sdb_ = sdb;
|
||||||
context_ = context;
|
context_ = context;
|
||||||
gen_module_ = gen_module;
|
gen_module_ = gen_module;
|
||||||
|
engine_ = engine;
|
||||||
di_builder_ = NULL;
|
di_builder_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,11 +198,12 @@ void ModuleGenerator::AddMissingImport(FunctionSymbol* fn) {
|
||||||
|
|
||||||
if (FLAGS_trace_kernel_calls) {
|
if (FLAGS_trace_kernel_calls) {
|
||||||
Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
|
Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
|
||||||
b.CreateCall3(
|
b.CreateCall4(
|
||||||
traceKernelCall,
|
traceKernelCall,
|
||||||
f->arg_begin(),
|
f->arg_begin(),
|
||||||
b.getInt64(fn->start_address),
|
b.getInt64(fn->start_address),
|
||||||
++f->arg_begin());
|
++f->arg_begin(),
|
||||||
|
b.getInt64((uint64_t)fn->kernel_export));
|
||||||
}
|
}
|
||||||
|
|
||||||
b.CreateRetVoid();
|
b.CreateRetVoid();
|
||||||
|
@ -221,18 +224,37 @@ void ModuleGenerator::AddPresentImport(FunctionSymbol* fn) {
|
||||||
Module *m = gen_module_;
|
Module *m = gen_module_;
|
||||||
LLVMContext& context = m->getContext();
|
LLVMContext& context = m->getContext();
|
||||||
|
|
||||||
// Add the extern.
|
const DataLayout* dl = engine_->getDataLayout();
|
||||||
|
Type* intPtrTy = dl->getIntPtrType(context);
|
||||||
|
Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context));
|
||||||
|
|
||||||
|
// Add the externs.
|
||||||
|
// We have both the shim function pointer and the shim data pointer.
|
||||||
char shim_name[256];
|
char shim_name[256];
|
||||||
xesnprintfa(shim_name, XECOUNT(shim_name),
|
xesnprintfa(shim_name, XECOUNT(shim_name),
|
||||||
"__shim__%s", fn->kernel_export->name);
|
"__shim_%s", fn->kernel_export->name);
|
||||||
|
char shim_data_name[256];
|
||||||
|
xesnprintfa(shim_data_name, XECOUNT(shim_data_name),
|
||||||
|
"__shim_data_%s", fn->kernel_export->name);
|
||||||
std::vector<Type*> shimArgs;
|
std::vector<Type*> shimArgs;
|
||||||
shimArgs.push_back(PointerType::getUnqual(Type::getInt8Ty(context)));
|
shimArgs.push_back(int8PtrTy);
|
||||||
|
shimArgs.push_back(int8PtrTy);
|
||||||
FunctionType* shimTy = FunctionType::get(
|
FunctionType* shimTy = FunctionType::get(
|
||||||
Type::getVoidTy(context), shimArgs, false);
|
Type::getVoidTy(context), shimArgs, false);
|
||||||
Function* shim = Function::Create(
|
Function* shim = Function::Create(
|
||||||
shimTy, Function::ExternalLinkage, shim_name, m);
|
shimTy, Function::ExternalLinkage, shim_name, m);
|
||||||
// engine_->addGlobalMapping(shim,
|
|
||||||
// (void*)fn->kernel_export->function_data.shim);
|
GlobalVariable* gv = new GlobalVariable(
|
||||||
|
*m, int8PtrTy, true, GlobalValue::ExternalLinkage, 0,
|
||||||
|
shim_data_name);
|
||||||
|
|
||||||
|
// TODO(benvanik): don't initialize on startup - move to exec_module
|
||||||
|
gv->setInitializer(ConstantExpr::getIntToPtr(
|
||||||
|
ConstantInt::get(intPtrTy,
|
||||||
|
(uintptr_t)fn->kernel_export->function_data.shim_data),
|
||||||
|
int8PtrTy));
|
||||||
|
engine_->addGlobalMapping(shim,
|
||||||
|
(void*)fn->kernel_export->function_data.shim);
|
||||||
|
|
||||||
// Create the function (and setup args/attributes/etc).
|
// Create the function (and setup args/attributes/etc).
|
||||||
Function* f = CreateFunctionDefinition(fn->name);
|
Function* f = CreateFunctionDefinition(fn->name);
|
||||||
|
@ -242,16 +264,18 @@ void ModuleGenerator::AddPresentImport(FunctionSymbol* fn) {
|
||||||
|
|
||||||
if (FLAGS_trace_kernel_calls) {
|
if (FLAGS_trace_kernel_calls) {
|
||||||
Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
|
Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
|
||||||
b.CreateCall3(
|
b.CreateCall4(
|
||||||
traceKernelCall,
|
traceKernelCall,
|
||||||
f->arg_begin(),
|
f->arg_begin(),
|
||||||
b.getInt64(fn->start_address),
|
b.getInt64(fn->start_address),
|
||||||
++f->arg_begin());
|
++f->arg_begin(),
|
||||||
|
b.getInt64((uint64_t)fn->kernel_export));
|
||||||
}
|
}
|
||||||
|
|
||||||
b.CreateCall(
|
b.CreateCall2(
|
||||||
shim,
|
shim,
|
||||||
f->arg_begin());
|
f->arg_begin(),
|
||||||
|
b.CreateLoad(gv));
|
||||||
|
|
||||||
b.CreateRetVoid();
|
b.CreateRetVoid();
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,8 @@ int ExecModule::Prepare() {
|
||||||
// Build the module from the source code.
|
// Build the module from the source code.
|
||||||
codegen_ = auto_ptr<ModuleGenerator>(new ModuleGenerator(
|
codegen_ = auto_ptr<ModuleGenerator>(new ModuleGenerator(
|
||||||
memory_, export_resolver_.get(), module_name_, module_path_,
|
memory_, export_resolver_.get(), module_name_, module_path_,
|
||||||
sdb_.get(), context_.get(), gen_module_.get()));
|
sdb_.get(), context_.get(), gen_module_.get(),
|
||||||
|
engine_.get()));
|
||||||
XEEXPECTZERO(codegen_->Generate());
|
XEEXPECTZERO(codegen_->Generate());
|
||||||
|
|
||||||
// Write to cache.
|
// Write to cache.
|
||||||
|
@ -248,14 +249,16 @@ void XeInvalidInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) {
|
||||||
XELOGCPU("INVALID INSTRUCTION %.8X %.8X", cia, data);
|
XELOGCPU("INVALID INSTRUCTION %.8X %.8X", cia, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XeTraceKernelCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia) {
|
void XeTraceKernelCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia,
|
||||||
// TODO(benvanik): get names
|
KernelExport* kernel_export) {
|
||||||
XELOGCPU("TRACE: %.8X -> k.%.8X", (uint32_t)call_ia - 4, (uint32_t)cia);
|
XELOGCPU("TRACE: %.8X -> k.%.8X (%s)", (uint32_t)call_ia - 4, (uint32_t)cia,
|
||||||
|
kernel_export ? kernel_export->name : "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
void XeTraceUserCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia) {
|
void XeTraceUserCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia,
|
||||||
// TODO(benvanik): get names
|
FunctionSymbol* fn) {
|
||||||
XELOGCPU("TRACE: %.8X -> u.%.8X", (uint32_t)call_ia - 4, (uint32_t)cia);
|
XELOGCPU("TRACE: %.8X -> u.%.8X (%s)", (uint32_t)call_ia - 4, (uint32_t)cia,
|
||||||
|
fn->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XeTraceInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) {
|
void XeTraceInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) {
|
||||||
|
@ -271,8 +274,8 @@ void XeTraceInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) {
|
||||||
int ExecModule::InjectGlobals() {
|
int ExecModule::InjectGlobals() {
|
||||||
LLVMContext& context = *context_.get();
|
LLVMContext& context = *context_.get();
|
||||||
const DataLayout* dl = engine_->getDataLayout();
|
const DataLayout* dl = engine_->getDataLayout();
|
||||||
Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context));
|
|
||||||
Type* intPtrTy = dl->getIntPtrType(context);
|
Type* intPtrTy = dl->getIntPtrType(context);
|
||||||
|
Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context));
|
||||||
GlobalVariable* gv;
|
GlobalVariable* gv;
|
||||||
|
|
||||||
// xe_memory_base
|
// xe_memory_base
|
||||||
|
@ -326,6 +329,7 @@ int ExecModule::InjectGlobals() {
|
||||||
traceCallArgs.push_back(int8PtrTy);
|
traceCallArgs.push_back(int8PtrTy);
|
||||||
traceCallArgs.push_back(Type::getInt64Ty(context));
|
traceCallArgs.push_back(Type::getInt64Ty(context));
|
||||||
traceCallArgs.push_back(Type::getInt64Ty(context));
|
traceCallArgs.push_back(Type::getInt64Ty(context));
|
||||||
|
traceCallArgs.push_back(Type::getInt64Ty(context));
|
||||||
FunctionType* traceCallTy = FunctionType::get(
|
FunctionType* traceCallTy = FunctionType::get(
|
||||||
Type::getVoidTy(context), traceCallArgs, false);
|
Type::getVoidTy(context), traceCallArgs, false);
|
||||||
std::vector<Type*> traceInstructionArgs;
|
std::vector<Type*> traceInstructionArgs;
|
||||||
|
@ -371,10 +375,10 @@ int ExecModule::Init() {
|
||||||
} else {
|
} else {
|
||||||
if (kernel_export->is_implemented) {
|
if (kernel_export->is_implemented) {
|
||||||
// Implemented - replace with pointer.
|
// Implemented - replace with pointer.
|
||||||
*slot = kernel_export->variable_ptr;
|
*slot = XESWAP32BE(kernel_export->variable_ptr);
|
||||||
} else {
|
} else {
|
||||||
// Not implemented - write with a dummy value.
|
// Not implemented - write with a dummy value.
|
||||||
*slot = 0xDEADBEEF;
|
*slot = XESWAP32BE(0xDEADBEEF);
|
||||||
XELOGCPU("WARNING: imported a variable with no value: %s",
|
XELOGCPU("WARNING: imported a variable with no value: %s",
|
||||||
kernel_export->name);
|
kernel_export->name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
#include <xenia/cpu/thread_state.h>
|
#include <xenia/cpu/thread_state.h>
|
||||||
|
|
||||||
|
#include <xenia/core/memory.h>
|
||||||
|
#include <xenia/cpu/processor.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::cpu;
|
using namespace xe::cpu;
|
||||||
|
@ -19,10 +22,12 @@ ThreadState::ThreadState(
|
||||||
uint32_t stack_address, uint32_t stack_size) {
|
uint32_t stack_address, uint32_t stack_size) {
|
||||||
stack_address_ = stack_address;
|
stack_address_ = stack_address;
|
||||||
stack_size_ = stack_size;
|
stack_size_ = stack_size;
|
||||||
|
memory_ = processor->memory();
|
||||||
|
|
||||||
xe_zero_struct(&ppc_state_, sizeof(ppc_state_));
|
xe_zero_struct(&ppc_state_, sizeof(ppc_state_));
|
||||||
|
|
||||||
// Stash pointers to common structures that callbacks may need.
|
// Stash pointers to common structures that callbacks may need.
|
||||||
|
ppc_state_.membase = xe_memory_addr(memory_, 0);
|
||||||
ppc_state_.processor = processor;
|
ppc_state_.processor = processor;
|
||||||
ppc_state_.thread_state = this;
|
ppc_state_.thread_state = this;
|
||||||
|
|
||||||
|
@ -31,6 +36,7 @@ ThreadState::ThreadState(
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadState::~ThreadState() {
|
ThreadState::~ThreadState() {
|
||||||
|
xe_memory_release(memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
xe_ppc_state_t* ThreadState::ppc_state() {
|
xe_ppc_state_t* ThreadState::ppc_state() {
|
||||||
|
|
|
@ -31,6 +31,7 @@ void ExportResolver::RegisterTable(
|
||||||
for (size_t n = 0; n < count; n++) {
|
for (size_t n = 0; n < count; n++) {
|
||||||
exports[n].is_implemented = false;
|
exports[n].is_implemented = false;
|
||||||
exports[n].variable_ptr = 0;
|
exports[n].variable_ptr = 0;
|
||||||
|
exports[n].function_data.shim_data = NULL;
|
||||||
exports[n].function_data.shim = NULL;
|
exports[n].function_data.shim = NULL;
|
||||||
exports[n].function_data.impl = NULL;
|
exports[n].function_data.impl = NULL;
|
||||||
}
|
}
|
||||||
|
@ -69,13 +70,14 @@ void ExportResolver::SetVariableMapping(const char* library_name,
|
||||||
kernel_export->variable_ptr = value;
|
kernel_export->variable_ptr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportResolver::SetFunctionMapping(const char* library_name,
|
void ExportResolver::SetFunctionMapping(
|
||||||
const uint32_t ordinal,
|
const char* library_name, const uint32_t ordinal,
|
||||||
xe_kernel_export_shim_fn shim,
|
void* shim_data, xe_kernel_export_shim_fn shim,
|
||||||
xe_kernel_export_impl_fn impl) {
|
xe_kernel_export_impl_fn impl) {
|
||||||
KernelExport* kernel_export = GetExportByOrdinal(library_name, ordinal);
|
KernelExport* kernel_export = GetExportByOrdinal(library_name, ordinal);
|
||||||
XEASSERTNOTNULL(kernel_export);
|
XEASSERTNOTNULL(kernel_export);
|
||||||
kernel_export->is_implemented = true;
|
kernel_export->is_implemented = true;
|
||||||
|
kernel_export->function_data.shim_data = shim_data;
|
||||||
kernel_export->function_data.shim = shim;
|
kernel_export->function_data.shim = shim;
|
||||||
kernel_export->function_data.impl = impl;
|
kernel_export->function_data.impl = impl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 "kernel/modules/xboxkrnl/kernel_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::kernel;
|
||||||
|
using namespace xe::kernel::xboxkrnl;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KernelState::KernelState(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
|
shared_ptr<ExportResolver> export_resolver) {
|
||||||
|
pal = xe_pal_retain(pal);
|
||||||
|
memory = xe_memory_retain(memory);
|
||||||
|
export_resolver_ = export_resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelState::~KernelState() {
|
||||||
|
xe_memory_release(memory);
|
||||||
|
xe_pal_release(pal);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_KERNEL_MODULES_XBOXKRNL_KERNEL_STATE_H_
|
||||||
|
#define XENIA_KERNEL_MODULES_XBOXKRNL_KERNEL_STATE_H_
|
||||||
|
|
||||||
|
#include <xenia/common.h>
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/kernel/export.h>
|
||||||
|
#include <xenia/kernel/kernel_module.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
|
||||||
|
class KernelState {
|
||||||
|
public:
|
||||||
|
KernelState(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
|
shared_ptr<ExportResolver> export_resolver);
|
||||||
|
~KernelState();
|
||||||
|
|
||||||
|
xe_pal_ref pal;
|
||||||
|
xe_memory_ref memory;
|
||||||
|
|
||||||
|
private:
|
||||||
|
shared_ptr<ExportResolver> export_resolver_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xboxkrnl
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_KERNEL_STATE_H_
|
|
@ -1,6 +1,9 @@
|
||||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'kernel_state.cc',
|
||||||
|
'xboxkrnl_hal.cc',
|
||||||
|
'xboxkrnl_memory.cc',
|
||||||
'xboxkrnl_module.cc',
|
'xboxkrnl_module.cc',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 "kernel/modules/xboxkrnl/xboxkrnl_hal.h"
|
||||||
|
|
||||||
|
#include "kernel/shim_utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::kernel;
|
||||||
|
using namespace xe::kernel::xboxkrnl;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
void HalReturnToFirmware_shim(
|
||||||
|
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||||
|
// void
|
||||||
|
// IN FIRMWARE_REENTRY Routine
|
||||||
|
|
||||||
|
// Routine must be 1 'HalRebootRoutine'
|
||||||
|
uint32_t routine = SHIM_GET_ARG_32(0);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
XT("HalReturnToFirmware(%d)"),
|
||||||
|
routine);
|
||||||
|
|
||||||
|
// TODO(benvank): diediedie much more gracefully
|
||||||
|
// Not sure how to blast back up the stack in LLVM without exceptions, though.
|
||||||
|
XELOGE(XT("Game requested shutdown via HalReturnToFirmware"));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xe::kernel::xboxkrnl::RegisterHalExports(
|
||||||
|
ExportResolver* export_resolver, KernelState* state) {
|
||||||
|
#define SHIM_SET_MAPPING(ordinal, shim, impl) \
|
||||||
|
export_resolver->SetFunctionMapping("xboxkrnl.exe", ordinal, \
|
||||||
|
state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl)
|
||||||
|
|
||||||
|
SHIM_SET_MAPPING(0x00000028, HalReturnToFirmware_shim, NULL);
|
||||||
|
|
||||||
|
#undef SET_MAPPING
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_KERNEL_MODULES_XBOXKRNL_HAL_H_
|
||||||
|
#define XENIA_KERNEL_MODULES_XBOXKRNL_HAL_H_
|
||||||
|
|
||||||
|
#include "kernel/modules/xboxkrnl/kernel_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
|
||||||
|
void RegisterHalExports(ExportResolver* export_resolver, KernelState* state);
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xboxkrnl
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_HAL_H_
|
|
@ -0,0 +1,112 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 "kernel/modules/xboxkrnl/xboxkrnl_memory.h"
|
||||||
|
|
||||||
|
#include "kernel/shim_utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::kernel;
|
||||||
|
using namespace xe::kernel::xboxkrnl;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
void NtAllocateVirtualMemory_shim(
|
||||||
|
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||||
|
// NTSTATUS
|
||||||
|
// _Inout_ PVOID *BaseAddress,
|
||||||
|
// _In_ ULONG_PTR ZeroBits,
|
||||||
|
// _Inout_ PSIZE_T RegionSize,
|
||||||
|
// _In_ ULONG AllocationType,
|
||||||
|
// _In_ ULONG Protect
|
||||||
|
// ? handle?
|
||||||
|
|
||||||
|
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||||
|
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||||
|
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
|
||||||
|
// MEM_COMMIT | MEM_PHYSICAL | MEM_RESERVE | MEM_RESET | MEM_TOP_DOWN
|
||||||
|
uint32_t allocation_type = SHIM_GET_ARG_32(2);
|
||||||
|
// PAGE_NOACCESS | PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE |
|
||||||
|
// PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_GUARD | PAGE_NOCACHE |
|
||||||
|
// PAGE_WRITECOMBINE
|
||||||
|
uint32_t protect_bits = SHIM_GET_ARG_32(3);
|
||||||
|
uint32_t unknown = SHIM_GET_ARG_32(4);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
XT("NtAllocateVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X, %.8X)"),
|
||||||
|
base_addr_ptr, base_addr_value,
|
||||||
|
region_size_ptr, region_size_value,
|
||||||
|
allocation_type, protect_bits, unknown);
|
||||||
|
|
||||||
|
// TODO(benvanik): alloc memory
|
||||||
|
|
||||||
|
// Possible return codes:
|
||||||
|
// STATUS_ACCESS_DENIED
|
||||||
|
// STATUS_ALREADY_COMMITTED
|
||||||
|
// STATUS_COMMITMENT_LIMIT
|
||||||
|
// STATUS_CONFLICTING_ADDRESSES
|
||||||
|
// STATUS_INSUFFICIENT_RESOURCES
|
||||||
|
// STATUS_INVALID_HANDLE
|
||||||
|
// STATUS_INVALID_PAGE_PROTECTION
|
||||||
|
// STATUS_NO_MEMORY
|
||||||
|
// STATUS_OBJECT_TYPE_MISMATCH
|
||||||
|
// STATUS_PROCESS_IS_TERMINATING
|
||||||
|
SHIM_SET_RETURN(0xC0000017);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NtFreeVirtualMemory_shim(
|
||||||
|
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||||
|
// NTSTATUS
|
||||||
|
// _Inout_ PVOID *BaseAddress,
|
||||||
|
// _Inout_ PSIZE_T RegionSize,
|
||||||
|
// _In_ ULONG FreeType
|
||||||
|
// ? handle?
|
||||||
|
|
||||||
|
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||||
|
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||||
|
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
|
||||||
|
// MEM_DECOMMIT | MEM_RELEASE
|
||||||
|
uint32_t free_type = SHIM_GET_ARG_32(2);
|
||||||
|
uint32_t unknown = SHIM_GET_ARG_32(3);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
XT("NtFreeVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X)"),
|
||||||
|
base_addr_ptr, base_addr_value,
|
||||||
|
region_size_ptr, region_size_value,
|
||||||
|
free_type, unknown);
|
||||||
|
|
||||||
|
// TODO(benvanik): free memory
|
||||||
|
|
||||||
|
// Possible return codes:
|
||||||
|
// STATUS_ACCESS_DENIED
|
||||||
|
// STATUS_INVALID_HANDLE
|
||||||
|
// STATUS_OBJECT_TYPE_MISMATCH
|
||||||
|
SHIM_SET_RETURN(0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xe::kernel::xboxkrnl::RegisterMemoryExports(
|
||||||
|
ExportResolver* export_resolver, KernelState* state) {
|
||||||
|
#define SHIM_SET_MAPPING(ordinal, shim, impl) \
|
||||||
|
export_resolver->SetFunctionMapping("xboxkrnl.exe", ordinal, \
|
||||||
|
state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl)
|
||||||
|
|
||||||
|
SHIM_SET_MAPPING(0x000000CC, NtAllocateVirtualMemory_shim, NULL);
|
||||||
|
SHIM_SET_MAPPING(0x000000DC, NtFreeVirtualMemory_shim, NULL);
|
||||||
|
|
||||||
|
#undef SET_MAPPING
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_KERNEL_MODULES_XBOXKRNL_MEMORY_H_
|
||||||
|
#define XENIA_KERNEL_MODULES_XBOXKRNL_MEMORY_H_
|
||||||
|
|
||||||
|
#include "kernel/modules/xboxkrnl/kernel_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
|
||||||
|
void RegisterMemoryExports(ExportResolver* export_resolver, KernelState* state);
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xboxkrnl
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MEMORY_H_
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
|
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
|
||||||
|
|
||||||
|
#include "kernel/modules/xboxkrnl/kernel_state.h"
|
||||||
|
#include "kernel/modules/xboxkrnl/xboxkrnl_hal.h"
|
||||||
|
#include "kernel/modules/xboxkrnl/xboxkrnl_memory.h"
|
||||||
#include "kernel/modules/xboxkrnl/xboxkrnl_table.h"
|
#include "kernel/modules/xboxkrnl/xboxkrnl_table.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +51,14 @@ XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
resolver->RegisterTable(
|
resolver->RegisterTable(
|
||||||
"xboxkrnl.exe", xboxkrnl_export_table, XECOUNT(xboxkrnl_export_table));
|
"xboxkrnl.exe", xboxkrnl_export_table, XECOUNT(xboxkrnl_export_table));
|
||||||
|
|
||||||
|
// Setup the kernel state instance.
|
||||||
|
// This is where all kernel objects are kept while running.
|
||||||
|
kernel_state = auto_ptr<KernelState>(new KernelState(pal, memory, resolver));
|
||||||
|
|
||||||
|
// Register all exported functions.
|
||||||
|
RegisterHalExports(resolver.get(), kernel_state.get());
|
||||||
|
RegisterMemoryExports(resolver.get(), kernel_state.get());
|
||||||
|
|
||||||
// TODO(benvanik): alloc heap memory somewhere in user space
|
// TODO(benvanik): alloc heap memory somewhere in user space
|
||||||
// TODO(benvanik): tools for reading/writing to heap memory
|
// TODO(benvanik): tools for reading/writing to heap memory
|
||||||
|
|
||||||
|
@ -55,15 +66,15 @@ XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
// KeDebugMonitorData
|
// KeDebugMonitorData
|
||||||
resolver->SetVariableMapping(
|
resolver->SetVariableMapping(
|
||||||
"xboxkrnl.exe", 0x00000059,
|
"xboxkrnl.exe", 0x00000059,
|
||||||
0);
|
0x40001000);
|
||||||
// XboxHardwareInfo
|
// XboxHardwareInfo
|
||||||
resolver->SetVariableMapping(
|
resolver->SetVariableMapping(
|
||||||
"xboxkrnl.exe", 0x00000156,
|
"xboxkrnl.exe", 0x00000156,
|
||||||
0);
|
0x40002000);
|
||||||
// XexExecutableModuleHandle
|
// XexExecutableModuleHandle
|
||||||
resolver->SetVariableMapping(
|
resolver->SetVariableMapping(
|
||||||
"xboxkrnl.exe", 0x00000193,
|
"xboxkrnl.exe", 0x00000193,
|
||||||
0);
|
0x40000000);
|
||||||
|
|
||||||
// 0x0000012B, RtlImageXexHeaderField
|
// 0x0000012B, RtlImageXexHeaderField
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,17 @@ namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xboxkrnl {
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
class KernelState;
|
||||||
|
|
||||||
|
|
||||||
class XboxkrnlModule : public KernelModule {
|
class XboxkrnlModule : public KernelModule {
|
||||||
public:
|
public:
|
||||||
XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
|
XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
shared_ptr<ExportResolver> resolver);
|
shared_ptr<ExportResolver> resolver);
|
||||||
virtual ~XboxkrnlModule();
|
virtual ~XboxkrnlModule();
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto_ptr<KernelState> kernel_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,5 +39,4 @@ public:
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
|
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_KERNEL_SHIM_UTILS_H_
|
||||||
|
#define XENIA_KERNEL_SHIM_UTILS_H_
|
||||||
|
|
||||||
|
#include <xenia/common.h>
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/cpu/ppc.h>
|
||||||
|
#include <xenia/kernel/export.h>
|
||||||
|
#include <xenia/kernel/kernel_module.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
|
||||||
|
|
||||||
|
#define SHIM_MEM_ADDR(a) (ppc_state->membase + a)
|
||||||
|
|
||||||
|
#define SHIM_MEM_32(a) (uint32_t)XEGETUINT32BE(SHIM_MEM_ADDR(a));
|
||||||
|
#define SHIM_SET_MEM_32(a, v) (*(uint32_t*)SHIM_MEM_ADDR(a)) = XESWAP32(v)
|
||||||
|
|
||||||
|
#define SHIM_GPR_32(n) (uint32_t)(ppc_state->r[n])
|
||||||
|
#define SHIM_SET_GPR_32(n, v) ppc_state->r[n] = (uint64_t)((v) & UINT32_MAX)
|
||||||
|
#define SHIM_GPR_64(n) ppc_state->r[n]
|
||||||
|
#define SHIM_SET_GPR_64(n, v) ppc_state->r[n] = (uint64_t)(v)
|
||||||
|
|
||||||
|
#define SHIM_GET_ARG_32(n) SHIM_GPR_32(3 + n)
|
||||||
|
#define SHIM_GET_ARG_64(n) SHIM_GPR_64(3 + n)
|
||||||
|
#define SHIM_SET_RETURN(v) SHIM_SET_GPR_64(3, v)
|
||||||
|
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_SHIM_UTILS_H_
|
Loading…
Reference in New Issue