Cleaning up LLVM exports and adding an access violation trap.

This commit is contained in:
Ben Vanik 2013-01-30 14:52:41 -08:00
parent 23378443e8
commit 2ecacedaa6
7 changed files with 258 additions and 148 deletions

View File

@ -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();

View File

@ -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;
}

View File

@ -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.

View File

@ -34,6 +34,7 @@
#include <xenia/cpu/ppc/state.h>
#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 : "<unknown>");
// 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<Type*> 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<Type*> 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<Type*> 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<Type*> 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<Type*> 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;
}

172
src/cpu/llvm_exports.cc Normal file
View File

@ -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 <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <xenia/cpu/sdb.h>
#include <xenia/cpu/ppc/instr.h>
#include <xenia/cpu/ppc/state.h>
#include <xenia/kernel/export.h>
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 : "<unknown>");
// 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<Type*> 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<Type*> 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<Type*> 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<Type*> 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<Type*> 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<Type*> 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);
}

38
src/cpu/llvm_exports.h Normal file
View File

@ -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 <xenia/common.h>
#include <xenia/core.h>
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_

View File

@ -3,6 +3,7 @@
'sources': [
'cpu.cc',
'exec_module.cc',
'llvm_exports.cc',
'processor.cc',
'sdb.cc',
'thread_state.cc',