diff --git a/include/xenia/cpu/codegen/function_generator.h b/include/xenia/cpu/codegen/function_generator.h index ca53a29cd..af2a04ac7 100644 --- a/include/xenia/cpu/codegen/function_generator.h +++ b/include/xenia/cpu/codegen/function_generator.h @@ -85,9 +85,11 @@ public: void update_gpr_value(uint32_t n, llvm::Value* value); llvm::Value* GetMembase(); - llvm::Value* GetMemoryAddress(llvm::Value* addr); - llvm::Value* ReadMemory(llvm::Value* addr, uint32_t size, bool extend); - void WriteMemory(llvm::Value* addr, uint32_t size, llvm::Value* value); + llvm::Value* GetMemoryAddress(uint32_t cia, llvm::Value* addr); + llvm::Value* ReadMemory( + uint32_t cia, llvm::Value* addr, uint32_t size, bool extend); + void WriteMemory( + uint32_t cia, llvm::Value* addr, uint32_t size, llvm::Value* value); private: void GenerateSharedBlocks(); diff --git a/src/cpu/codegen/emit_memory.cc b/src/cpu/codegen/emit_memory.cc index 903e38b22..eee72ce50 100644 --- a/src/cpu/codegen/emit_memory.cc +++ b/src/cpu/codegen/emit_memory.cc @@ -47,7 +47,7 @@ XEEMITTER(lbz, 0x88000000, D )(FunctionGenerator& g, IRBuilder<>& b, I if (i.D.RA) { ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); } - Value* v = g.ReadMemory(ea, 1, false); + Value* v = g.ReadMemory(i.address, ea, 1, false); g.update_gpr_value(i.D.RT, v); return 0; @@ -66,7 +66,7 @@ XEEMITTER(lbzu, 0x8C000000, D )(FunctionGenerator& g, IRBuilder<>& b, I // RA <- EA Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = g.ReadMemory(ea, 1, false); + Value* v = g.ReadMemory(i.address, ea, 1, false); g.update_gpr_value(i.D.RT, v); g.update_gpr_value(i.D.RA, ea); @@ -86,7 +86,7 @@ XEEMITTER(lbzux, 0x7C0000EE, X )(FunctionGenerator& g, IRBuilder<>& b, I // RA <- EA Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); - Value* v = g.ReadMemory(ea, 1, false); + Value* v = g.ReadMemory(i.address, ea, 1, false); g.update_gpr_value(i.X.RT, v); g.update_gpr_value(i.X.RA, ea); @@ -116,7 +116,7 @@ XEEMITTER(lbzx, 0x7C0000AE, X )(FunctionGenerator& g, IRBuilder<>& b, I if (i.X.RA) { ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); } - Value* v = g.ReadMemory(ea, 1, false); + Value* v = g.ReadMemory(i.address, ea, 1, false); g.update_gpr_value(i.X.RT, v); return 0; @@ -145,7 +145,7 @@ XEEMITTER(ld, 0xE8000000, DS )(FunctionGenerator& g, IRBuilder<>& b, I if (i.DS.RA) { ea = b.CreateAdd(g.gpr_value(i.DS.RA), ea); } - Value* v = g.ReadMemory(ea, 8, false); + Value* v = g.ReadMemory(i.address, ea, 8, false); g.update_gpr_value(i.DS.RT, v); return 0; @@ -165,7 +165,7 @@ XEEMITTER(ldu, 0xE8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, I Value* ea = b.CreateAdd(g.gpr_value(i.DS.RA), b.getInt64(XEEXTS16(i.DS.DS << 2))); - Value* v = g.ReadMemory(ea, 8, false); + Value* v = g.ReadMemory(i.address, ea, 8, false); g.update_gpr_value(i.DS.RT, v); g.update_gpr_value(i.DS.RA, ea); @@ -225,7 +225,7 @@ XEEMITTER(lhz, 0xA0000000, D )(FunctionGenerator& g, IRBuilder<>& b, I if (i.D.RA) { ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); } - Value* v = g.ReadMemory(ea, 2, false); + Value* v = g.ReadMemory(i.address, ea, 2, false); g.update_gpr_value(i.D.RT, v); return 0; @@ -284,7 +284,7 @@ XEEMITTER(lwz, 0x80000000, D )(FunctionGenerator& g, IRBuilder<>& b, I if (i.D.RA) { ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); } - Value* v = g.ReadMemory(ea, 4, false); + Value* v = g.ReadMemory(i.address, ea, 4, false); g.update_gpr_value(i.D.RT, v); return 0; @@ -303,7 +303,7 @@ XEEMITTER(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, I // RA <- EA Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = g.ReadMemory(ea, 4, false); + Value* v = g.ReadMemory(i.address, ea, 4, false); g.update_gpr_value(i.D.RT, v); g.update_gpr_value(i.D.RA, ea); @@ -338,7 +338,7 @@ XEEMITTER(lwzx, 0x7C00002E, X )(FunctionGenerator& g, IRBuilder<>& b, I if (i.X.RA) { ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); } - Value* v = g.ReadMemory(ea, 4, false); + Value* v = g.ReadMemory(i.address, ea, 4, false); g.update_gpr_value(i.X.RT, v); return 0; @@ -371,7 +371,7 @@ XEEMITTER(stb, 0x98000000, D )(FunctionGenerator& g, IRBuilder<>& b, I ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); } Value* v = g.gpr_value(i.D.RT); - g.WriteMemory(ea, 1, v); + g.WriteMemory(i.address, ea, 1, v); return 0; } @@ -390,7 +390,7 @@ XEEMITTER(stbu, 0x9C000000, D )(FunctionGenerator& g, IRBuilder<>& b, I Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); Value* v = g.gpr_value(i.D.RT); - g.WriteMemory(ea, 1, v); + g.WriteMemory(i.address, ea, 1, v); g.update_gpr_value(i.D.RA, ea); return 0; @@ -430,7 +430,7 @@ XEEMITTER(std, 0xF8000000, DS )(FunctionGenerator& g, IRBuilder<>& b, I ea = b.CreateAdd(g.gpr_value(i.DS.RA), ea); } Value* v = g.gpr_value(i.DS.RT); - g.WriteMemory(ea, 8, v); + g.WriteMemory(i.address, ea, 8, v); return 0; } @@ -450,7 +450,7 @@ XEEMITTER(stdu, 0xF8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, I Value* ea = b.CreateAdd(g.gpr_value(i.DS.RA), b.getInt64(XEEXTS16(i.DS.DS << 2))); Value* v = g.gpr_value(i.DS.RT); - g.WriteMemory(ea, 8, v); + g.WriteMemory(i.address, ea, 8, v); g.update_gpr_value(i.DS.RA, ea); return 0; @@ -490,7 +490,7 @@ XEEMITTER(sth, 0xB0000000, D )(FunctionGenerator& g, IRBuilder<>& b, I ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); } Value* v = g.gpr_value(i.D.RT); - g.WriteMemory(ea, 2, v); + g.WriteMemory(i.address, ea, 2, v); return 0; } @@ -510,7 +510,7 @@ XEEMITTER(sthu, 0xB4000000, D )(FunctionGenerator& g, IRBuilder<>& b, I Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); Value* v = g.gpr_value(i.D.RT); - g.WriteMemory(ea, 2, v); + g.WriteMemory(i.address, ea, 2, v); g.update_gpr_value(i.D.RA, ea); return 0; @@ -545,7 +545,7 @@ XEEMITTER(sthx, 0x7C00032E, X )(FunctionGenerator& g, IRBuilder<>& b, I ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); } Value* v = g.gpr_value(i.X.RT); - g.WriteMemory(ea, 2, v); + g.WriteMemory(i.address, ea, 2, v); return 0; } @@ -574,7 +574,7 @@ XEEMITTER(stw, 0x90000000, D )(FunctionGenerator& g, IRBuilder<>& b, I ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); } Value* v = g.gpr_value(i.D.RT); - g.WriteMemory(ea, 4, v); + g.WriteMemory(i.address, ea, 4, v); return 0; } @@ -594,7 +594,7 @@ XEEMITTER(stwu, 0x94000000, D )(FunctionGenerator& g, IRBuilder<>& b, I Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); Value* v = g.gpr_value(i.D.RT); - g.WriteMemory(ea, 4, v); + g.WriteMemory(i.address, ea, 4, v); g.update_gpr_value(i.D.RA, ea); return 0; @@ -629,7 +629,7 @@ XEEMITTER(stwx, 0x7C00012E, X )(FunctionGenerator& g, IRBuilder<>& b, I ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); } Value* v = g.gpr_value(i.X.RT); - g.WriteMemory(ea, 4, v); + g.WriteMemory(i.address, ea, 4, v); return 0; } diff --git a/src/cpu/codegen/function_generator.cc b/src/cpu/codegen/function_generator.cc index 8bc8809fa..7b2385c02 100644 --- a/src/cpu/codegen/function_generator.cc +++ b/src/cpu/codegen/function_generator.cc @@ -874,7 +874,7 @@ Value* FunctionGenerator::GetMembase() { return builder_->CreateLoad(v); } -Value* FunctionGenerator::GetMemoryAddress(Value* addr) { +Value* FunctionGenerator::GetMemoryAddress(uint32_t cia, Value* addr) { IRBuilder<>& b = *builder_; // Input address is always in 32-bit space. @@ -890,9 +890,12 @@ Value* FunctionGenerator::GetMemoryAddress(Value* addr) { b.CreateCondBr(gt, valid_bb, invalid_bb); b.SetInsertPoint(invalid_bb); - Function* debugtrap = Intrinsic::getDeclaration( - gen_module_, Intrinsic::debugtrap); - b.CreateCall(debugtrap); + Value* access_violation = gen_module_->getFunction("XeAccessViolation"); + SpillRegisters(); + b.CreateCall3(access_violation, + gen_fn_->arg_begin(), + b.getInt32(cia), + addr); b.CreateBr(valid_bb); b.SetInsertPoint(valid_bb); @@ -902,7 +905,8 @@ Value* FunctionGenerator::GetMemoryAddress(Value* addr) { return b.CreateInBoundsGEP(GetMembase(), addr); } -Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) { +Value* FunctionGenerator::ReadMemory( + uint32_t cia, Value* addr, uint32_t size, bool extend) { IRBuilder<>& b = *builder_; Type* dataTy = NULL; @@ -929,7 +933,7 @@ Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) { } PointerType* pointerTy = PointerType::getUnqual(dataTy); - Value* address = GetMemoryAddress(addr); + Value* address = GetMemoryAddress(cia, addr); Value* ptr = b.CreatePointerCast(address, pointerTy); Value* value = b.CreateLoad(ptr); @@ -944,7 +948,8 @@ Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) { return value; } -void FunctionGenerator::WriteMemory(Value* addr, uint32_t size, Value* value) { +void FunctionGenerator::WriteMemory( + uint32_t cia, Value* addr, uint32_t size, Value* value) { IRBuilder<>& b = *builder_; Type* dataTy = NULL; @@ -971,7 +976,7 @@ void FunctionGenerator::WriteMemory(Value* addr, uint32_t size, Value* value) { } PointerType* pointerTy = PointerType::getUnqual(dataTy); - Value* address = GetMemoryAddress(addr); + Value* address = GetMemoryAddress(cia, addr); Value* ptr = b.CreatePointerCast(address, pointerTy); // Truncate, if required. diff --git a/src/cpu/exec_module.cc b/src/cpu/exec_module.cc index 98948698b..8075af366 100644 --- a/src/cpu/exec_module.cc +++ b/src/cpu/exec_module.cc @@ -34,6 +34,7 @@ #include #include "cpu/cpu-private.h" +#include "cpu/llvm_exports.h" #include "cpu/xethunk/xethunk.h" @@ -217,13 +218,13 @@ int ExecModule::Prepare() { XEEXPECTZERO(Init()); // Force JIT of all functions. - for (Module::iterator it = gen_module_->begin(); it != gen_module_->end(); - ++it) { - Function* fn = it; - if (!fn->isDeclaration()) { - engine_->getPointerToFunction(fn); - } - } + // for (Module::iterator it = gen_module_->begin(); it != gen_module_->end(); + // ++it) { + // Function* fn = it; + // if (!fn->isDeclaration()) { + // engine_->getPointerToFunction(fn); + // } + // } result_code = 0; XECLEANUP: @@ -234,61 +235,6 @@ void ExecModule::AddFunctionsToMap(FunctionMap& map) { codegen_->AddFunctionsToMap(map); } -void XeTrap(xe_ppc_state_t* state, uint32_t cia) { - printf("TRAP"); - XEASSERTALWAYS(); -} - -void XeIndirectBranch(xe_ppc_state_t* state, uint64_t target, uint64_t br_ia) { - printf("INDIRECT BRANCH %.8X -> %.8X\n", (uint32_t)br_ia, (uint32_t)target); - XEASSERTALWAYS(); -} - -void XeInvalidInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) { - ppc::InstrData i; - i.address = cia; - i.code = data; - i.type = ppc::GetInstrType(i.code); - - if (!i.type) { - XELOGCPU(XT("INVALID INSTRUCTION %.8X: %.8X ???"), - i.address, i.code); - } else if (i.type->disassemble) { - ppc::InstrDisasm d; - i.type->disassemble(i, d); - std::string disasm; - d.Dump(disasm); - XELOGCPU(XT("INVALID INSTRUCTION %.8X: %.8X %s"), - i.address, i.code, disasm.c_str()); - } else { - XELOGCPU(XT("INVALID INSTRUCTION %.8X: %.8X %s"), - i.address, i.code, i.type->name); - } -} - -void XeTraceKernelCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia, - KernelExport* kernel_export) { - XELOGCPU(XT("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, - FunctionSymbol* fn) { - XELOGCPU(XT("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) { - ppc::InstrType* type = ppc::GetInstrType(data); - XELOGCPU(XT("TRACE: %.8X %.8X %s %s"), - cia, data, - type && type->emit ? " " : "X", - type ? type->name : ""); - - // TODO(benvanik): better disassembly, printing of current register values/etc -} - int ExecModule::InjectGlobals() { LLVMContext& context = *context_.get(); const DataLayout* dl = engine_->getDataLayout(); @@ -311,61 +257,7 @@ int ExecModule::InjectGlobals() { ConstantInt::get(intPtrTy, (uintptr_t)xe_memory_addr(memory_, 0)), int8PtrTy)); - // Control methods: - std::vector trapArgs; - trapArgs.push_back(int8PtrTy); - trapArgs.push_back(Type::getInt32Ty(context)); - FunctionType* trapTy = FunctionType::get( - Type::getVoidTy(context), trapArgs, false); - engine_->addGlobalMapping(Function::Create( - trapTy, Function::ExternalLinkage, "XeTrap", - gen_module_.get()), (void*)&XeTrap); - - std::vector indirectBranchArgs; - indirectBranchArgs.push_back(int8PtrTy); - indirectBranchArgs.push_back(Type::getInt64Ty(context)); - indirectBranchArgs.push_back(Type::getInt64Ty(context)); - FunctionType* indirectBranchTy = FunctionType::get( - Type::getVoidTy(context), indirectBranchArgs, false); - engine_->addGlobalMapping(Function::Create( - indirectBranchTy, Function::ExternalLinkage, "XeIndirectBranch", - gen_module_.get()), (void*)&XeIndirectBranch); - - // Debugging methods: - std::vector invalidInstructionArgs; - invalidInstructionArgs.push_back(int8PtrTy); - invalidInstructionArgs.push_back(Type::getInt32Ty(context)); - invalidInstructionArgs.push_back(Type::getInt32Ty(context)); - FunctionType* invalidInstructionTy = FunctionType::get( - Type::getVoidTy(context), invalidInstructionArgs, false); - engine_->addGlobalMapping(Function::Create( - invalidInstructionTy, Function::ExternalLinkage, "XeInvalidInstruction", - gen_module_.get()), (void*)&XeInvalidInstruction); - - // Tracing methods: - std::vector traceCallArgs; - 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 traceInstructionArgs; - traceInstructionArgs.push_back(int8PtrTy); - traceInstructionArgs.push_back(Type::getInt32Ty(context)); - traceInstructionArgs.push_back(Type::getInt32Ty(context)); - FunctionType* traceInstructionTy = FunctionType::get( - Type::getVoidTy(context), traceInstructionArgs, false); - - 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); + SetupLlvmExports(gen_module_.get(), dl, engine_.get()); return 0; } diff --git a/src/cpu/llvm_exports.cc b/src/cpu/llvm_exports.cc new file mode 100644 index 000000000..7843bb31c --- /dev/null +++ b/src/cpu/llvm_exports.cc @@ -0,0 +1,172 @@ +/** + ****************************************************************************** + * 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 "cpu/llvm_exports.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +using namespace llvm; +using namespace xe; +using namespace xe::cpu; +using namespace xe::cpu::sdb; +using namespace xe::kernel; + + +namespace { + + +void XeTrap(xe_ppc_state_t* state, uint32_t cia) { + XELOGE(XT("TRAP")); + XEASSERTALWAYS(); +} + +void XeIndirectBranch(xe_ppc_state_t* state, uint64_t target, uint64_t br_ia) { + XELOGCPU(XT("INDIRECT BRANCH %.8X -> %.8X"), + (uint32_t)br_ia, (uint32_t)target); + XEASSERTALWAYS(); +} + +void XeInvalidInstruction(xe_ppc_state_t* state, uint32_t cia, uint32_t data) { + ppc::InstrData i; + i.address = cia; + i.code = data; + i.type = ppc::GetInstrType(i.code); + + if (!i.type) { + XELOGCPU(XT("INVALID INSTRUCTION %.8X: %.8X ???"), + i.address, i.code); + } else if (i.type->disassemble) { + ppc::InstrDisasm d; + i.type->disassemble(i, d); + std::string disasm; + d.Dump(disasm); + XELOGCPU(XT("INVALID INSTRUCTION %.8X: %.8X %s"), + i.address, i.code, disasm.c_str()); + } else { + XELOGCPU(XT("INVALID INSTRUCTION %.8X: %.8X %s"), + i.address, i.code, i.type->name); + } +} + +void XeAccessViolation(xe_ppc_state_t* state, uint32_t cia, uint64_t ea) { + XELOGE(XT("INVALID ACCESS %.8X: tried to touch %.8X"), + cia, (uint32_t)ea); + XEASSERTALWAYS(); +} + +void XeTraceKernelCall(xe_ppc_state_t* state, uint64_t cia, uint64_t call_ia, + KernelExport* kernel_export) { + XELOGCPU(XT("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, + FunctionSymbol* fn) { + XELOGCPU(XT("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) { + ppc::InstrType* type = ppc::GetInstrType(data); + XELOGCPU(XT("TRACE: %.8X %.8X %s %s"), + cia, data, + type && type->emit ? " " : "X", + type ? type->name : ""); + + // TODO(benvanik): better disassembly, printing of current register values/etc +} + + +} + + +void xe::cpu::SetupLlvmExports(llvm::Module* module, + const llvm::DataLayout* dl, + llvm::ExecutionEngine* engine) { + LLVMContext& context = module->getContext(); + Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context)); + + // Control methods: + std::vector trapArgs; + trapArgs.push_back(int8PtrTy); + trapArgs.push_back(Type::getInt32Ty(context)); + FunctionType* trapTy = FunctionType::get( + Type::getVoidTy(context), trapArgs, false); + engine->addGlobalMapping(Function::Create( + trapTy, Function::ExternalLinkage, "XeTrap", + module), (void*)&XeTrap); + + std::vector indirectBranchArgs; + indirectBranchArgs.push_back(int8PtrTy); + indirectBranchArgs.push_back(Type::getInt64Ty(context)); + indirectBranchArgs.push_back(Type::getInt64Ty(context)); + FunctionType* indirectBranchTy = FunctionType::get( + Type::getVoidTy(context), indirectBranchArgs, false); + engine->addGlobalMapping(Function::Create( + indirectBranchTy, Function::ExternalLinkage, "XeIndirectBranch", + module), (void*)&XeIndirectBranch); + + // Debugging methods: + std::vector invalidInstructionArgs; + invalidInstructionArgs.push_back(int8PtrTy); + invalidInstructionArgs.push_back(Type::getInt32Ty(context)); + invalidInstructionArgs.push_back(Type::getInt32Ty(context)); + FunctionType* invalidInstructionTy = FunctionType::get( + Type::getVoidTy(context), invalidInstructionArgs, false); + engine->addGlobalMapping(Function::Create( + invalidInstructionTy, Function::ExternalLinkage, "XeInvalidInstruction", + module), (void*)&XeInvalidInstruction); + + std::vector accessViolationArgs; + accessViolationArgs.push_back(int8PtrTy); + accessViolationArgs.push_back(Type::getInt32Ty(context)); + accessViolationArgs.push_back(Type::getInt64Ty(context)); + FunctionType* accessViolationTy = FunctionType::get( + Type::getVoidTy(context), accessViolationArgs, false); + engine->addGlobalMapping(Function::Create( + accessViolationTy, Function::ExternalLinkage, "XeAccessViolation", + module), (void*)&XeAccessViolation); + + // Tracing methods: + std::vector traceCallArgs; + 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 traceInstructionArgs; + traceInstructionArgs.push_back(int8PtrTy); + traceInstructionArgs.push_back(Type::getInt32Ty(context)); + traceInstructionArgs.push_back(Type::getInt32Ty(context)); + FunctionType* traceInstructionTy = FunctionType::get( + Type::getVoidTy(context), traceInstructionArgs, false); + + engine->addGlobalMapping(Function::Create( + traceCallTy, Function::ExternalLinkage, "XeTraceKernelCall", + module), (void*)&XeTraceKernelCall); + engine->addGlobalMapping(Function::Create( + traceCallTy, Function::ExternalLinkage, "XeTraceUserCall", + module), (void*)&XeTraceUserCall); + engine->addGlobalMapping(Function::Create( + traceInstructionTy, Function::ExternalLinkage, "XeTraceInstruction", + module), (void*)&XeTraceInstruction); +} diff --git a/src/cpu/llvm_exports.h b/src/cpu/llvm_exports.h new file mode 100644 index 000000000..36c8ad1c0 --- /dev/null +++ b/src/cpu/llvm_exports.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * 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_CPU_LLVM_EXPORTS_H_ +#define XENIA_CPU_LLVM_EXPORTS_H_ + +#include +#include + + +namespace llvm { + class ExecutionEngine; + class LLVMContext; + class Module; + class DataLayout; +} + + +namespace xe { +namespace cpu { + + +void SetupLlvmExports(llvm::Module* module, + const llvm::DataLayout* dl, + llvm::ExecutionEngine* engine); + + +} // cpu +} // xe + + +#endif // XENIA_CPU_LLVM_EXPORTS_H_ diff --git a/src/cpu/sources.gypi b/src/cpu/sources.gypi index ac90e3708..3d2c0f7b8 100644 --- a/src/cpu/sources.gypi +++ b/src/cpu/sources.gypi @@ -3,6 +3,7 @@ 'sources': [ 'cpu.cc', 'exec_module.cc', + 'llvm_exports.cc', 'processor.cc', 'sdb.cc', 'thread_state.cc',