diff --git a/TODO.md b/TODO.md index 5e0feec96..8a20b909f 100644 --- a/TODO.md +++ b/TODO.md @@ -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. ``` -MISDECODING: andix - rlwinmx rlwimix rldiclx - -slwx -srawix ``` Overflow bits can be set via the intrinsics: diff --git a/private/runtest.sh b/private/runtest.sh index b05bbb88e..c8c145ef5 100755 --- a/private/runtest.sh +++ b/private/runtest.sh @@ -9,7 +9,7 @@ fi ./build/xenia/release/xenia-run \ private/$1 \ --optimize_ir_modules=true \ - --optimize_ir_functions=false \ + --optimize_ir_functions=true \ --trace_kernel_calls=true \ --trace_user_calls=false \ --trace_instructions=false \ diff --git a/src/cpu/codegen/emit_alu.cc b/src/cpu/codegen/emit_alu.cc index eb26e9237..e1eaacc0f 100644 --- a/src/cpu/codegen/emit_alu.cc +++ b/src/cpu/codegen/emit_alu.cc @@ -539,7 +539,7 @@ XEEMITTER(andix, 0x70000000, D )(FunctionGenerator& g, IRBuilder<>& b, I // With cr0 update. 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) { @@ -805,7 +805,6 @@ XEEMITTER(rlwinmx, 0x54000000, M )(FunctionGenerator& g, IRBuilder<>& b, I // 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(); return 1; } diff --git a/src/cpu/codegen/emit_control.cc b/src/cpu/codegen/emit_control.cc index 1bfdbd10c..dc9557cac 100644 --- a/src/cpu/codegen/emit_control.cc +++ b/src/cpu/codegen/emit_control.cc @@ -173,6 +173,7 @@ XEEMITTER(bcx, 0x40000000, B )(FunctionGenerator& g, IRBuilder<>& b, I // Decrement counter. Value* ctr = g.ctr_value(); ctr = b.CreateSub(ctr, b.getInt64(1)); + g.update_ctr_value(ctr); // Ctr check. if (XESELECTBITS(i.B.BO, 1, 1)) { @@ -520,7 +521,7 @@ int XeEmitTrap(FunctionGenerator& g, IRBuilder<>& b, InstrData& i, b.SetInsertPoint(trap_bb); g.SpillRegisters(); // 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(), b.getInt32(i.address)); b.CreateBr(after_bb); diff --git a/src/cpu/codegen/function_generator.cc b/src/cpu/codegen/function_generator.cc index 498a40e7c..4a9630c87 100644 --- a/src/cpu/codegen/function_generator.cc +++ b/src/cpu/codegen/function_generator.cc @@ -117,7 +117,7 @@ void FunctionGenerator::GenerateBasicBlocks() { if (FLAGS_trace_user_calls) { SpillRegisters(); - Value* traceUserCall = gen_module_->getGlobalVariable("XeTraceUserCall"); + Value* traceUserCall = gen_module_->getFunction("XeTraceUserCall"); builder_->CreateCall3( traceUserCall, gen_fn_->arg_begin(), @@ -162,7 +162,7 @@ void FunctionGenerator::GenerateBasicBlocks() { void FunctionGenerator::GenerateSharedBlocks() { 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. // 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))); Value* invalidInstruction = - gen_module_->getGlobalVariable("XeInvalidInstruction"); + gen_module_->getFunction("XeInvalidInstruction"); Value* traceInstruction = - gen_module_->getGlobalVariable("XeTraceInstruction"); + gen_module_->getFunction("XeTraceInstruction"); // Walk instructions in block. uint8_t* p = xe_memory_addr(memory_, 0); @@ -390,7 +390,7 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target, SpillRegisters(); // 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, gen_fn_->arg_begin(), target, @@ -861,6 +861,9 @@ Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) { } 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* address = b.CreateInBoundsGEP(GetMembase(), offset_addr); 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); + // Input address is always in 32-bit space. + addr = b.CreateAnd(addr, UINT_MAX); + Value* offset_addr = b.CreateAdd(addr, b.getInt64(size)); Value* address = b.CreateInBoundsGEP(GetMembase(), offset_addr); Value* ptr = b.CreatePointerCast(address, pointerTy); diff --git a/src/cpu/codegen/module_generator.cc b/src/cpu/codegen/module_generator.cc index 78bfed1e4..79a7ba734 100644 --- a/src/cpu/codegen/module_generator.cc +++ b/src/cpu/codegen/module_generator.cc @@ -77,7 +77,7 @@ int ModuleGenerator::Generate() { } di_builder_ = new DIBuilder(*gen_module_); di_builder_->createCompileUnit( - 0, + dwarf::DW_LANG_C99, //0x8010, StringRef(module_name_), StringRef(dir), StringRef("xenia"), @@ -196,7 +196,7 @@ void ModuleGenerator::AddMissingImport(FunctionSymbol* fn) { IRBuilder<> builder(block); if (FLAGS_trace_kernel_calls) { - Value* traceKernelCall = m->getGlobalVariable("XeTraceKernelCall"); + Value* traceKernelCall = m->getFunction("XeTraceKernelCall"); builder.CreateCall3( traceKernelCall, f->arg_begin(), diff --git a/src/cpu/exec_module.cc b/src/cpu/exec_module.cc index a98d9f435..133d08810 100644 --- a/src/cpu/exec_module.cc +++ b/src/cpu/exec_module.cc @@ -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) { // 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) { // 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) { @@ -286,10 +286,9 @@ int ExecModule::InjectGlobals() { trapArgs.push_back(Type::getInt32Ty(context)); FunctionType* trapTy = FunctionType::get( Type::getVoidTy(context), trapArgs, false); - gv = new GlobalVariable(*gen_module_, trapTy, true, - GlobalVariable::ExternalLinkage, 0, - "XeTrap"); - engine_->addGlobalMapping(gv, (void*)&XeTrap); + engine_->addGlobalMapping(Function::Create( + trapTy, Function::ExternalLinkage, "XeTrap", + gen_module_.get()), (void*)&XeTrap); std::vector indirectBranchArgs; indirectBranchArgs.push_back(int8PtrTy); @@ -297,10 +296,9 @@ int ExecModule::InjectGlobals() { indirectBranchArgs.push_back(Type::getInt64Ty(context)); FunctionType* indirectBranchTy = FunctionType::get( Type::getVoidTy(context), indirectBranchArgs, false); - gv = new GlobalVariable(*gen_module_, indirectBranchTy, true, - GlobalVariable::ExternalLinkage, 0, - "XeIndirectBranch"); - engine_->addGlobalMapping(gv, (void*)&XeIndirectBranch); + engine_->addGlobalMapping(Function::Create( + indirectBranchTy, Function::ExternalLinkage, "XeIndirectBranch", + gen_module_.get()), (void*)&XeIndirectBranch); // Debugging methods: std::vector invalidInstructionArgs; @@ -309,10 +307,9 @@ int ExecModule::InjectGlobals() { invalidInstructionArgs.push_back(Type::getInt32Ty(context)); FunctionType* invalidInstructionTy = FunctionType::get( Type::getVoidTy(context), invalidInstructionArgs, false); - gv = new GlobalVariable(*gen_module_, invalidInstructionTy, true, - GlobalVariable::ExternalLinkage, 0, - "XeInvalidInstruction"); - engine_->addGlobalMapping(gv, (void*)&XeInvalidInstruction); + engine_->addGlobalMapping(Function::Create( + invalidInstructionTy, Function::ExternalLinkage, "XeInvalidInstruction", + gen_module_.get()), (void*)&XeInvalidInstruction); // Tracing methods: std::vector traceCallArgs; @@ -328,18 +325,15 @@ int ExecModule::InjectGlobals() { FunctionType* traceInstructionTy = FunctionType::get( Type::getVoidTy(context), traceInstructionArgs, false); - gv = new GlobalVariable(*gen_module_, traceCallTy, true, - GlobalValue::ExternalLinkage, 0, - "XeTraceKernelCall"); - engine_->addGlobalMapping(gv, (void*)&XeTraceKernelCall); - gv = new GlobalVariable(*gen_module_, traceCallTy, true, - GlobalValue::ExternalLinkage, 0, - "XeTraceUserCall"); - engine_->addGlobalMapping(gv, (void*)&XeTraceUserCall); - gv = new GlobalVariable(*gen_module_, traceInstructionTy, true, - GlobalValue::ExternalLinkage, 0, - "XeTraceInstruction"); - engine_->addGlobalMapping(gv, (void*)&XeTraceInstruction); + engine_->addGlobalMapping(Function::Create( + traceCallTy, Function::ExternalLinkage, "XeTraceKernelCall", + gen_module_.get()), (void*)&XeTraceKernelCall); + engine_->addGlobalMapping(Function::Create( + traceCallTy, Function::ExternalLinkage, "XeTraceUserCall", + gen_module_.get()), (void*)&XeTraceUserCall); + engine_->addGlobalMapping(Function::Create( + traceInstructionTy, Function::ExternalLinkage, "XeTraceInstruction", + gen_module_.get()), (void*)&XeTraceInstruction); return 0; } diff --git a/src/cpu/processor.cc b/src/cpu/processor.cc index a7331456d..b6ba7e753 100644 --- a/src/cpu/processor.cc +++ b/src/cpu/processor.cc @@ -99,7 +99,7 @@ int Processor::Setup() { std::string error_message; engine_ = shared_ptr( ExecutionEngine::create(dummy_module, false, &error_message, - CodeGenOpt::Aggressive)); + CodeGenOpt::Aggressive, false)); if (!engine_) { return 1; } diff --git a/src/kernel/runtime.cc b/src/kernel/runtime.cc index 82f3cc1da..4bb136141 100644 --- a/src/kernel/runtime.cc +++ b/src/kernel/runtime.cc @@ -13,6 +13,7 @@ using namespace xe; +using namespace xe::cpu; using namespace xe::kernel; @@ -131,13 +132,11 @@ XECLEANUP: } 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 // 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?). // xex_header->exe_heap_size; @@ -149,6 +148,19 @@ void Runtime::LaunchModule(UserModule* user_module) { // Wait until thread completes. // XLARGE_INTEGER timeout = XINFINITE; // 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) { diff --git a/xenia.gyp b/xenia.gyp index b2a36eb4b..56268de61 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -73,6 +73,10 @@ ], 'direct_dependent_settings': { + 'include_dirs': [ + '