Kernel calls and variables now working and tracing better.
This commit is contained in:
@@ -117,23 +117,26 @@ void FunctionGenerator::PopInsertPoint() {
|
||||
}
|
||||
|
||||
void FunctionGenerator::GenerateBasicBlocks() {
|
||||
IRBuilder<>& b = *builder_;
|
||||
|
||||
// Always add an entry block.
|
||||
BasicBlock* entry = BasicBlock::Create(*context_, "entry", gen_fn_);
|
||||
builder_->SetInsertPoint(entry);
|
||||
b.SetInsertPoint(entry);
|
||||
|
||||
if (FLAGS_trace_user_calls) {
|
||||
SpillRegisters();
|
||||
Value* traceUserCall = gen_module_->getFunction("XeTraceUserCall");
|
||||
builder_->CreateCall3(
|
||||
b.CreateCall4(
|
||||
traceUserCall,
|
||||
gen_fn_->arg_begin(),
|
||||
builder_->getInt64(fn_->start_address),
|
||||
++gen_fn_->arg_begin());
|
||||
b.getInt64(fn_->start_address),
|
||||
++gen_fn_->arg_begin(),
|
||||
b.getInt64((uint64_t)fn_));
|
||||
}
|
||||
|
||||
// If this function is empty, abort!
|
||||
if (!fn_->blocks.size()) {
|
||||
builder_->CreateRetVoid();
|
||||
b.CreateRetVoid();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -214,13 +217,15 @@ void FunctionGenerator::GenerateSharedBlocks() {
|
||||
|
||||
void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||
BasicBlock* bb) {
|
||||
IRBuilder<>& b = *builder_;
|
||||
|
||||
printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address);
|
||||
|
||||
fn_block_ = block;
|
||||
bb_ = bb;
|
||||
|
||||
// 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)));
|
||||
|
||||
Value* invalidInstruction =
|
||||
@@ -238,21 +243,21 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||
|
||||
if (FLAGS_trace_instructions) {
|
||||
SpillRegisters();
|
||||
builder_->CreateCall3(
|
||||
b.CreateCall3(
|
||||
traceInstruction,
|
||||
gen_fn_->arg_begin(),
|
||||
builder_->getInt32(i.address),
|
||||
builder_->getInt32(i.code));
|
||||
b.getInt32(i.address),
|
||||
b.getInt32(i.code));
|
||||
}
|
||||
|
||||
if (!i.type) {
|
||||
XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code);
|
||||
SpillRegisters();
|
||||
builder_->CreateCall3(
|
||||
b.CreateCall3(
|
||||
invalidInstruction,
|
||||
gen_fn_->arg_begin(),
|
||||
builder_->getInt32(i.address),
|
||||
builder_->getInt32(i.code));
|
||||
b.getInt32(i.address),
|
||||
b.getInt32(i.code));
|
||||
continue;
|
||||
}
|
||||
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",
|
||||
ia, i.code, i.type->name);
|
||||
SpillRegisters();
|
||||
builder_->CreateCall3(
|
||||
b.CreateCall3(
|
||||
invalidInstruction,
|
||||
gen_fn_->arg_begin(),
|
||||
builder_->getInt32(i.address),
|
||||
builder_->getInt32(i.code));
|
||||
b.getInt32(i.address),
|
||||
b.getInt32(i.code));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,13 +290,13 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||
if (block->outgoing_type == FunctionBlock::kTargetNone) {
|
||||
BasicBlock* next_bb = GetNextBasicBlock();
|
||||
XEASSERTNOTNULL(next_bb);
|
||||
builder_->CreateBr(next_bb);
|
||||
b.CreateBr(next_bb);
|
||||
} else if (block->outgoing_type == FunctionBlock::kTargetUnknown) {
|
||||
// Hrm.
|
||||
// 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",
|
||||
fn_->start_address, block->start_address);
|
||||
builder_->CreateRetVoid();
|
||||
b.CreateRetVoid();
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (!external_indirection_block_) {
|
||||
// Setup locals in the entry block.
|
||||
builder_->SetInsertPoint(&gen_fn_->getEntryBlock());
|
||||
b.SetInsertPoint(&gen_fn_->getEntryBlock());
|
||||
locals_.indirection_target = b.CreateAlloca(
|
||||
b.getInt64Ty(), 0, "indirection_target");
|
||||
locals_.indirection_cia = b.CreateAlloca(
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <llvm/PassManager.h>
|
||||
#include <llvm/DebugInfo.h>
|
||||
#include <llvm/Analysis/Verifier.h>
|
||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||
#include <llvm/IR/Attributes.h>
|
||||
#include <llvm/IR/DataLayout.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
@@ -40,7 +41,7 @@ using namespace xe::kernel;
|
||||
ModuleGenerator::ModuleGenerator(
|
||||
xe_memory_ref memory, ExportResolver* export_resolver,
|
||||
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);
|
||||
export_resolver_ = export_resolver;
|
||||
module_name_ = xestrdupa(module_name);
|
||||
@@ -48,6 +49,7 @@ ModuleGenerator::ModuleGenerator(
|
||||
sdb_ = sdb;
|
||||
context_ = context;
|
||||
gen_module_ = gen_module;
|
||||
engine_ = engine;
|
||||
di_builder_ = NULL;
|
||||
}
|
||||
|
||||
@@ -196,11 +198,12 @@ void ModuleGenerator::AddMissingImport(FunctionSymbol* fn) {
|
||||
|
||||
if (FLAGS_trace_kernel_calls) {
|
||||
Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
|
||||
b.CreateCall3(
|
||||
b.CreateCall4(
|
||||
traceKernelCall,
|
||||
f->arg_begin(),
|
||||
b.getInt64(fn->start_address),
|
||||
++f->arg_begin());
|
||||
++f->arg_begin(),
|
||||
b.getInt64((uint64_t)fn->kernel_export));
|
||||
}
|
||||
|
||||
b.CreateRetVoid();
|
||||
@@ -221,18 +224,37 @@ void ModuleGenerator::AddPresentImport(FunctionSymbol* fn) {
|
||||
Module *m = gen_module_;
|
||||
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];
|
||||
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;
|
||||
shimArgs.push_back(PointerType::getUnqual(Type::getInt8Ty(context)));
|
||||
shimArgs.push_back(int8PtrTy);
|
||||
shimArgs.push_back(int8PtrTy);
|
||||
FunctionType* shimTy = FunctionType::get(
|
||||
Type::getVoidTy(context), shimArgs, false);
|
||||
Function* shim = Function::Create(
|
||||
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).
|
||||
Function* f = CreateFunctionDefinition(fn->name);
|
||||
@@ -242,16 +264,18 @@ void ModuleGenerator::AddPresentImport(FunctionSymbol* fn) {
|
||||
|
||||
if (FLAGS_trace_kernel_calls) {
|
||||
Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
|
||||
b.CreateCall3(
|
||||
b.CreateCall4(
|
||||
traceKernelCall,
|
||||
f->arg_begin(),
|
||||
b.getInt64(fn->start_address),
|
||||
++f->arg_begin());
|
||||
++f->arg_begin(),
|
||||
b.getInt64((uint64_t)fn->kernel_export));
|
||||
}
|
||||
|
||||
b.CreateCall(
|
||||
b.CreateCall2(
|
||||
shim,
|
||||
f->arg_begin());
|
||||
f->arg_begin(),
|
||||
b.CreateLoad(gv));
|
||||
|
||||
b.CreateRetVoid();
|
||||
|
||||
|
||||
@@ -162,7 +162,8 @@ int ExecModule::Prepare() {
|
||||
// Build the module from the source code.
|
||||
codegen_ = auto_ptr<ModuleGenerator>(new ModuleGenerator(
|
||||
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());
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void XeTraceKernelCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia) {
|
||||
// TODO(benvanik): get names
|
||||
XELOGCPU("TRACE: %.8X -> k.%.8X", (uint32_t)call_ia - 4, (uint32_t)cia);
|
||||
void XeTraceKernelCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia,
|
||||
KernelExport* kernel_export) {
|
||||
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) {
|
||||
// TODO(benvanik): get names
|
||||
XELOGCPU("TRACE: %.8X -> u.%.8X", (uint32_t)call_ia - 4, (uint32_t)cia);
|
||||
void XeTraceUserCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia,
|
||||
FunctionSymbol* fn) {
|
||||
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) {
|
||||
@@ -271,8 +274,8 @@ void XeTraceInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) {
|
||||
int ExecModule::InjectGlobals() {
|
||||
LLVMContext& context = *context_.get();
|
||||
const DataLayout* dl = engine_->getDataLayout();
|
||||
Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context));
|
||||
Type* intPtrTy = dl->getIntPtrType(context);
|
||||
Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context));
|
||||
GlobalVariable* gv;
|
||||
|
||||
// xe_memory_base
|
||||
@@ -326,6 +329,7 @@ int ExecModule::InjectGlobals() {
|
||||
traceCallArgs.push_back(int8PtrTy);
|
||||
traceCallArgs.push_back(Type::getInt64Ty(context));
|
||||
traceCallArgs.push_back(Type::getInt64Ty(context));
|
||||
traceCallArgs.push_back(Type::getInt64Ty(context));
|
||||
FunctionType* traceCallTy = FunctionType::get(
|
||||
Type::getVoidTy(context), traceCallArgs, false);
|
||||
std::vector<Type*> traceInstructionArgs;
|
||||
@@ -371,10 +375,10 @@ int ExecModule::Init() {
|
||||
} else {
|
||||
if (kernel_export->is_implemented) {
|
||||
// Implemented - replace with pointer.
|
||||
*slot = kernel_export->variable_ptr;
|
||||
*slot = XESWAP32BE(kernel_export->variable_ptr);
|
||||
} else {
|
||||
// Not implemented - write with a dummy value.
|
||||
*slot = 0xDEADBEEF;
|
||||
*slot = XESWAP32BE(0xDEADBEEF);
|
||||
XELOGCPU("WARNING: imported a variable with no value: %s",
|
||||
kernel_export->name);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
#include <xenia/cpu/thread_state.h>
|
||||
|
||||
#include <xenia/core/memory.h>
|
||||
#include <xenia/cpu/processor.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
@@ -19,10 +22,12 @@ ThreadState::ThreadState(
|
||||
uint32_t stack_address, uint32_t stack_size) {
|
||||
stack_address_ = stack_address;
|
||||
stack_size_ = stack_size;
|
||||
memory_ = processor->memory();
|
||||
|
||||
xe_zero_struct(&ppc_state_, sizeof(ppc_state_));
|
||||
|
||||
// Stash pointers to common structures that callbacks may need.
|
||||
ppc_state_.membase = xe_memory_addr(memory_, 0);
|
||||
ppc_state_.processor = processor;
|
||||
ppc_state_.thread_state = this;
|
||||
|
||||
@@ -31,6 +36,7 @@ ThreadState::ThreadState(
|
||||
}
|
||||
|
||||
ThreadState::~ThreadState() {
|
||||
xe_memory_release(memory_);
|
||||
}
|
||||
|
||||
xe_ppc_state_t* ThreadState::ppc_state() {
|
||||
|
||||
Reference in New Issue
Block a user