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:
parent
92a3e19cd9
commit
46d5a0b51d
5
TODO.md
5
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:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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<Type*> 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<Type*> 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<Type*> 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;
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ int Processor::Setup() {
|
|||
std::string error_message;
|
||||
engine_ = shared_ptr<ExecutionEngine>(
|
||||
ExecutionEngine::create(dummy_module, false, &error_message,
|
||||
CodeGenOpt::Aggressive));
|
||||
CodeGenOpt::Aggressive, false));
|
||||
if (!engine_) {
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue