Executing a bunch of instructions!

Very hacky module startup code, but can now start XEXs! Time to start
implementing kernel stuff.
This commit is contained in:
Ben Vanik 2013-01-27 22:14:24 -08:00
parent 92a3e19cd9
commit 46d5a0b51d
10 changed files with 57 additions and 46 deletions

View File

@ -6,14 +6,9 @@ Not sure the way I'm doing this is right. addic/subficx/etc set it to the value
of the overflow bit from the LLVM *_with_overflow intrinsic. of the overflow bit from the LLVM *_with_overflow intrinsic.
``` ```
MISDECODING: andix
rlwinmx rlwinmx
rlwimix rlwimix
rldiclx rldiclx
slwx
srawix
``` ```
Overflow bits can be set via the intrinsics: Overflow bits can be set via the intrinsics:

View File

@ -9,7 +9,7 @@ fi
./build/xenia/release/xenia-run \ ./build/xenia/release/xenia-run \
private/$1 \ private/$1 \
--optimize_ir_modules=true \ --optimize_ir_modules=true \
--optimize_ir_functions=false \ --optimize_ir_functions=true \
--trace_kernel_calls=true \ --trace_kernel_calls=true \
--trace_user_calls=false \ --trace_user_calls=false \
--trace_instructions=false \ --trace_instructions=false \

View File

@ -539,7 +539,7 @@ XEEMITTER(andix, 0x70000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
// With cr0 update. // With cr0 update.
g.update_cr_with_cond(0, v, b.getInt64(0), true); g.update_cr_with_cond(0, v, b.getInt64(0), true);
return 1; return 0;
} }
XEEMITTER(andisx, 0x74000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { XEEMITTER(andisx, 0x74000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
@ -805,7 +805,6 @@ XEEMITTER(rlwinmx, 0x54000000, M )(FunctionGenerator& g, IRBuilder<>& b, I
// g.update_cr_with_cond(0, v, b.getInt64(0), true); // g.update_cr_with_cond(0, v, b.getInt64(0), true);
// } // }
printf("rlwinmx %d %d %d\n", i.M.SH, i.M.MB, i.M.ME);
XEINSTRNOTIMPLEMENTED(); XEINSTRNOTIMPLEMENTED();
return 1; return 1;
} }

View File

@ -173,6 +173,7 @@ XEEMITTER(bcx, 0x40000000, B )(FunctionGenerator& g, IRBuilder<>& b, I
// Decrement counter. // Decrement counter.
Value* ctr = g.ctr_value(); Value* ctr = g.ctr_value();
ctr = b.CreateSub(ctr, b.getInt64(1)); ctr = b.CreateSub(ctr, b.getInt64(1));
g.update_ctr_value(ctr);
// Ctr check. // Ctr check.
if (XESELECTBITS(i.B.BO, 1, 1)) { if (XESELECTBITS(i.B.BO, 1, 1)) {
@ -520,7 +521,7 @@ int XeEmitTrap(FunctionGenerator& g, IRBuilder<>& b, InstrData& i,
b.SetInsertPoint(trap_bb); b.SetInsertPoint(trap_bb);
g.SpillRegisters(); g.SpillRegisters();
// TODO(benvanik): use @llvm.debugtrap? could make debugging better // TODO(benvanik): use @llvm.debugtrap? could make debugging better
b.CreateCall2(g.gen_module()->getGlobalVariable("XeTrap"), b.CreateCall2(g.gen_module()->getFunction("XeTrap"),
g.gen_fn()->arg_begin(), g.gen_fn()->arg_begin(),
b.getInt32(i.address)); b.getInt32(i.address));
b.CreateBr(after_bb); b.CreateBr(after_bb);

View File

@ -117,7 +117,7 @@ void FunctionGenerator::GenerateBasicBlocks() {
if (FLAGS_trace_user_calls) { if (FLAGS_trace_user_calls) {
SpillRegisters(); SpillRegisters();
Value* traceUserCall = gen_module_->getGlobalVariable("XeTraceUserCall"); Value* traceUserCall = gen_module_->getFunction("XeTraceUserCall");
builder_->CreateCall3( builder_->CreateCall3(
traceUserCall, traceUserCall,
gen_fn_->arg_begin(), gen_fn_->arg_begin(),
@ -162,7 +162,7 @@ void FunctionGenerator::GenerateBasicBlocks() {
void FunctionGenerator::GenerateSharedBlocks() { void FunctionGenerator::GenerateSharedBlocks() {
IRBuilder<>& b = *builder_; IRBuilder<>& b = *builder_;
Value* indirect_branch = gen_module_->getGlobalVariable("XeIndirectBranch"); Value* indirect_branch = gen_module_->getFunction("XeIndirectBranch");
// Setup initial register fill in the entry block. // Setup initial register fill in the entry block.
// We can only do this once all the locals have been created. // We can only do this once all the locals have been created.
@ -218,9 +218,9 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
//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 =
gen_module_->getGlobalVariable("XeInvalidInstruction"); gen_module_->getFunction("XeInvalidInstruction");
Value* traceInstruction = Value* traceInstruction =
gen_module_->getGlobalVariable("XeTraceInstruction"); gen_module_->getFunction("XeTraceInstruction");
// Walk instructions in block. // Walk instructions in block.
uint8_t* p = xe_memory_addr(memory_, 0); uint8_t* p = xe_memory_addr(memory_, 0);
@ -390,7 +390,7 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target,
SpillRegisters(); SpillRegisters();
// TODO(benvanik): keep function pointer lookup local. // TODO(benvanik): keep function pointer lookup local.
Value* indirect_branch = gen_module_->getGlobalVariable("XeIndirectBranch"); Value* indirect_branch = gen_module_->getFunction("XeIndirectBranch");
b.CreateCall3(indirect_branch, b.CreateCall3(indirect_branch,
gen_fn_->arg_begin(), gen_fn_->arg_begin(),
target, target,
@ -861,6 +861,9 @@ Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) {
} }
PointerType* pointerTy = PointerType::getUnqual(dataTy); PointerType* pointerTy = PointerType::getUnqual(dataTy);
// Input address is always in 32-bit space.
addr = b.CreateAnd(addr, UINT_MAX);
Value* offset_addr = b.CreateAdd(addr, b.getInt64(size)); Value* offset_addr = b.CreateAdd(addr, b.getInt64(size));
Value* address = b.CreateInBoundsGEP(GetMembase(), offset_addr); Value* address = b.CreateInBoundsGEP(GetMembase(), offset_addr);
Value* ptr = b.CreatePointerCast(address, pointerTy); Value* ptr = b.CreatePointerCast(address, pointerTy);
@ -890,6 +893,9 @@ void FunctionGenerator::WriteMemory(Value* addr, uint32_t size, Value* value) {
} }
PointerType* pointerTy = PointerType::getUnqual(dataTy); PointerType* pointerTy = PointerType::getUnqual(dataTy);
// Input address is always in 32-bit space.
addr = b.CreateAnd(addr, UINT_MAX);
Value* offset_addr = b.CreateAdd(addr, b.getInt64(size)); Value* offset_addr = b.CreateAdd(addr, b.getInt64(size));
Value* address = b.CreateInBoundsGEP(GetMembase(), offset_addr); Value* address = b.CreateInBoundsGEP(GetMembase(), offset_addr);
Value* ptr = b.CreatePointerCast(address, pointerTy); Value* ptr = b.CreatePointerCast(address, pointerTy);

View File

@ -77,7 +77,7 @@ int ModuleGenerator::Generate() {
} }
di_builder_ = new DIBuilder(*gen_module_); di_builder_ = new DIBuilder(*gen_module_);
di_builder_->createCompileUnit( di_builder_->createCompileUnit(
0, dwarf::DW_LANG_C99, //0x8010,
StringRef(module_name_), StringRef(module_name_),
StringRef(dir), StringRef(dir),
StringRef("xenia"), StringRef("xenia"),
@ -196,7 +196,7 @@ void ModuleGenerator::AddMissingImport(FunctionSymbol* fn) {
IRBuilder<> builder(block); IRBuilder<> builder(block);
if (FLAGS_trace_kernel_calls) { if (FLAGS_trace_kernel_calls) {
Value* traceKernelCall = m->getGlobalVariable("XeTraceKernelCall"); Value* traceKernelCall = m->getFunction("XeTraceKernelCall");
builder.CreateCall3( builder.CreateCall3(
traceKernelCall, traceKernelCall,
f->arg_begin(), f->arg_begin(),

View File

@ -240,12 +240,12 @@ void XeInvalidInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t 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 // TODO(benvanik): get names
XELOGCPU("TRACE: %.8X -> k.%.8X", (uint32_t)call_ia, (uint32_t)cia); XELOGCPU("TRACE: %.8X -> k.%.8X", (uint32_t)call_ia - 4, (uint32_t)cia);
} }
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 // TODO(benvanik): get names
XELOGCPU("TRACE: %.8X -> u.%.8X", (uint32_t)call_ia, (uint32_t)cia); XELOGCPU("TRACE: %.8X -> u.%.8X", (uint32_t)call_ia - 4, (uint32_t)cia);
} }
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) {
@ -286,10 +286,9 @@ int ExecModule::InjectGlobals() {
trapArgs.push_back(Type::getInt32Ty(context)); trapArgs.push_back(Type::getInt32Ty(context));
FunctionType* trapTy = FunctionType::get( FunctionType* trapTy = FunctionType::get(
Type::getVoidTy(context), trapArgs, false); Type::getVoidTy(context), trapArgs, false);
gv = new GlobalVariable(*gen_module_, trapTy, true, engine_->addGlobalMapping(Function::Create(
GlobalVariable::ExternalLinkage, 0, trapTy, Function::ExternalLinkage, "XeTrap",
"XeTrap"); gen_module_.get()), (void*)&XeTrap);
engine_->addGlobalMapping(gv, (void*)&XeTrap);
std::vector<Type*> indirectBranchArgs; std::vector<Type*> indirectBranchArgs;
indirectBranchArgs.push_back(int8PtrTy); indirectBranchArgs.push_back(int8PtrTy);
@ -297,10 +296,9 @@ int ExecModule::InjectGlobals() {
indirectBranchArgs.push_back(Type::getInt64Ty(context)); indirectBranchArgs.push_back(Type::getInt64Ty(context));
FunctionType* indirectBranchTy = FunctionType::get( FunctionType* indirectBranchTy = FunctionType::get(
Type::getVoidTy(context), indirectBranchArgs, false); Type::getVoidTy(context), indirectBranchArgs, false);
gv = new GlobalVariable(*gen_module_, indirectBranchTy, true, engine_->addGlobalMapping(Function::Create(
GlobalVariable::ExternalLinkage, 0, indirectBranchTy, Function::ExternalLinkage, "XeIndirectBranch",
"XeIndirectBranch"); gen_module_.get()), (void*)&XeIndirectBranch);
engine_->addGlobalMapping(gv, (void*)&XeIndirectBranch);
// Debugging methods: // Debugging methods:
std::vector<Type*> invalidInstructionArgs; std::vector<Type*> invalidInstructionArgs;
@ -309,10 +307,9 @@ int ExecModule::InjectGlobals() {
invalidInstructionArgs.push_back(Type::getInt32Ty(context)); invalidInstructionArgs.push_back(Type::getInt32Ty(context));
FunctionType* invalidInstructionTy = FunctionType::get( FunctionType* invalidInstructionTy = FunctionType::get(
Type::getVoidTy(context), invalidInstructionArgs, false); Type::getVoidTy(context), invalidInstructionArgs, false);
gv = new GlobalVariable(*gen_module_, invalidInstructionTy, true, engine_->addGlobalMapping(Function::Create(
GlobalVariable::ExternalLinkage, 0, invalidInstructionTy, Function::ExternalLinkage, "XeInvalidInstruction",
"XeInvalidInstruction"); gen_module_.get()), (void*)&XeInvalidInstruction);
engine_->addGlobalMapping(gv, (void*)&XeInvalidInstruction);
// Tracing methods: // Tracing methods:
std::vector<Type*> traceCallArgs; std::vector<Type*> traceCallArgs;
@ -328,18 +325,15 @@ int ExecModule::InjectGlobals() {
FunctionType* traceInstructionTy = FunctionType::get( FunctionType* traceInstructionTy = FunctionType::get(
Type::getVoidTy(context), traceInstructionArgs, false); Type::getVoidTy(context), traceInstructionArgs, false);
gv = new GlobalVariable(*gen_module_, traceCallTy, true, engine_->addGlobalMapping(Function::Create(
GlobalValue::ExternalLinkage, 0, traceCallTy, Function::ExternalLinkage, "XeTraceKernelCall",
"XeTraceKernelCall"); gen_module_.get()), (void*)&XeTraceKernelCall);
engine_->addGlobalMapping(gv, (void*)&XeTraceKernelCall); engine_->addGlobalMapping(Function::Create(
gv = new GlobalVariable(*gen_module_, traceCallTy, true, traceCallTy, Function::ExternalLinkage, "XeTraceUserCall",
GlobalValue::ExternalLinkage, 0, gen_module_.get()), (void*)&XeTraceUserCall);
"XeTraceUserCall"); engine_->addGlobalMapping(Function::Create(
engine_->addGlobalMapping(gv, (void*)&XeTraceUserCall); traceInstructionTy, Function::ExternalLinkage, "XeTraceInstruction",
gv = new GlobalVariable(*gen_module_, traceInstructionTy, true, gen_module_.get()), (void*)&XeTraceInstruction);
GlobalValue::ExternalLinkage, 0,
"XeTraceInstruction");
engine_->addGlobalMapping(gv, (void*)&XeTraceInstruction);
return 0; return 0;
} }

View File

@ -99,7 +99,7 @@ int Processor::Setup() {
std::string error_message; std::string error_message;
engine_ = shared_ptr<ExecutionEngine>( engine_ = shared_ptr<ExecutionEngine>(
ExecutionEngine::create(dummy_module, false, &error_message, ExecutionEngine::create(dummy_module, false, &error_message,
CodeGenOpt::Aggressive)); CodeGenOpt::Aggressive, false));
if (!engine_) { if (!engine_) {
return 1; return 1;
} }

View File

@ -13,6 +13,7 @@
using namespace xe; using namespace xe;
using namespace xe::cpu;
using namespace xe::kernel; using namespace xe::kernel;
@ -131,13 +132,11 @@ XECLEANUP:
} }
void Runtime::LaunchModule(UserModule* user_module) { void Runtime::LaunchModule(UserModule* user_module) {
//const xe_xex2_header_t *xex_header = xe_module_get_xex_header(module); const xe_xex2_header_t *xex_header = user_module->xex_header();
// TODO(benvanik): set as main module/etc // TODO(benvanik): set as main module/etc
// xekXexExecutableModuleHandle = xe_module_get_handle(module); // xekXexExecutableModuleHandle = xe_module_get_handle(module);
// XEEXPECTTRUE(XECPUPrepareModule(XEGetCPU(), module->xex, module->pe, module->address_space, module->address_space_size));
// Setup the heap (and TLS?). // Setup the heap (and TLS?).
// xex_header->exe_heap_size; // xex_header->exe_heap_size;
@ -149,6 +148,19 @@ void Runtime::LaunchModule(UserModule* user_module) {
// Wait until thread completes. // Wait until thread completes.
// XLARGE_INTEGER timeout = XINFINITE; // XLARGE_INTEGER timeout = XINFINITE;
// xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout); // xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout);
// Simulate a thread.
uint32_t stack_size = xex_header->exe_stack_size;
if (stack_size < 16 * 1024 * 1024) {
stack_size = 16 * 1024 * 1024;
}
ThreadState* thread_state = processor_->AllocThread(
0x80000000, stack_size);
// Execute test.
processor_->Execute(thread_state, xex_header->exe_entry_point);
processor_->DeallocThread(thread_state);
} }
UserModule* Runtime::GetModule(const xechar_t* path) { UserModule* Runtime::GetModule(const xechar_t* path) {

View File

@ -73,6 +73,10 @@
], ],
'direct_dependent_settings': { 'direct_dependent_settings': {
'include_dirs': [
'<!@(<(llvm_config) --includedir)',
],
'target_conditions': [ 'target_conditions': [
['_type=="shared_library"', { ['_type=="shared_library"', {
'cflags': [ 'cflags': [