Cleaning up function registers and setting up CR.

This commit is contained in:
Ben Vanik 2013-01-26 01:25:31 -08:00
parent 9b3d96a8ae
commit 733fe85d37
5 changed files with 267 additions and 159 deletions

View File

@ -41,6 +41,9 @@ public:
llvm::Function* gen_fn();
sdb::FunctionBlock* fn_block();
void PushInsertPoint();
void PopInsertPoint();
void GenerateBasicBlocks();
llvm::BasicBlock* GetBasicBlock(uint32_t address);
llvm::BasicBlock* GetNextBasicBlock();
@ -57,8 +60,7 @@ public:
llvm::Value* cia_value();
llvm::Value* SetupRegisterLocal(uint32_t offset, llvm::Type* type,
const char* name);
llvm::Value* SetupLocal(llvm::Type* type, const char* name);
void FillRegisters();
void SpillRegisters();
@ -69,8 +71,8 @@ public:
llvm::Value* ctr_value();
void update_ctr_value(llvm::Value* value);
llvm::Value* cr_value();
void update_cr_value(llvm::Value* value);
llvm::Value* cr_value(uint32_t n);
void update_cr_value(uint32_t n, llvm::Value* value);
llvm::Value* gpr_value(uint32_t n);
void update_gpr_value(uint32_t n, llvm::Value* value);
@ -84,6 +86,12 @@ private:
void GenerateSharedBlocks();
void GenerateBasicBlock(sdb::FunctionBlock* block, llvm::BasicBlock* bb);
void setup_xer();
void setup_lr();
void setup_ctr();
void setup_cr(uint32_t n);
void setup_gpr(uint32_t n);
xe_memory_ref memory_;
sdb::SymbolDatabase* sdb_;
sdb::FunctionSymbol* fn_;
@ -97,6 +105,9 @@ private:
llvm::BasicBlock* bb_;
llvm::IRBuilder<>* builder_;
std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock::iterator> >
insert_points_;
std::map<uint32_t, llvm::BasicBlock*> bbs_;
// Address of the instruction being generated.
@ -109,7 +120,7 @@ private:
llvm::Value* xer;
llvm::Value* lr;
llvm::Value* ctr;
llvm::Value* cr;
llvm::Value* cr[8];
llvm::Value* gpr[32];
} locals_;
};

View File

@ -62,6 +62,18 @@ static inline int32_t XEEXTS16(uint32_t v) {
static inline int32_t XEEXTS26(uint32_t v) {
return v & 0x02000000 ? (int32_t)v | 0xFC000000 : (int32_t)(v);
}
static inline uint64_t XEMASK(uint32_t mstart, uint32_t mstop) {
// if mstart ≤ mstop then
// mask[mstart:mstop] = ones
// mask[all other bits] = zeros
// else
// mask[mstart:63] = ones
// mask[0:mstop] = ones
// mask[all other bits] = zeros
uint64_t value =
(UINT64_MAX >> mstart) ^ ((mstop >= 63) ? 0 : UINT64_MAX >> (mstop + 1));
return mstart <= mstop ? value : ~value;
}
typedef struct {

View File

@ -242,23 +242,25 @@ XEEMITTER(subfzex, 0x7C000190, XO )(FunctionGenerator& g, IRBuilder<>& b, I
void XeEmitCompareCore(FunctionGenerator& g, IRBuilder<>& b,
Value* lhs, Value* rhs, uint32_t BF, bool is_signed) {
// bit0 = RA < RB
// bit1 = RA > RB
// bit2 = RA = RB
// bit3 = XER[SO]
// Bits are reversed:
// 0123
// 3210
Value* is_lt = is_signed ?
b.CreateICmpSLT(lhs, rhs) : b.CreateICmpULT(lhs, rhs);
Value* is_gt = is_signed ?
b.CreateICmpSGT(lhs, rhs) : b.CreateICmpUGT(lhs, rhs);
Value* cp = b.CreateSelect(is_gt, b.getInt8(0x2), b.getInt8(0x1));
Value* c = b.CreateSelect(is_lt, b.getInt8(0x4), cp);
c = b.CreateZExt(c, b.getInt64Ty());
Value* cp = b.CreateSelect(is_gt, b.getInt8(1 << 2), b.getInt8(1 << 1));
Value* c = b.CreateSelect(is_lt, b.getInt8(1 << 3), cp);
// TODO(benvanik): set bit 4 to XER[SO]
// Insert the 4 bits into their location in the CR.
Value* cr = g.cr_value();
uint32_t mask = XEBITMASK((4 + BF) * 4, (4 + BF) * 4 + 4);
cr = b.CreateAnd(cr, mask);
cr = b.CreateOr(cr, b.CreateShl(c, (4 + BF) * 4));
g.update_cr_value(cr);
g.update_cr_value(BF, c);
}
XEEMITTER(cmp, 0x7C000000, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
@ -660,14 +662,6 @@ XEEMITTER(rlwinmx, 0x54000000, M )(FunctionGenerator& g, IRBuilder<>& b, I
return 0;
}
// if mstart ≤ mstop then
// mask[mstart:mstop] = ones
// mask[all other bits] = zeros
// else
// mask[mstart:63] = ones
// mask[0:mstop] = ones
// mask[all other bits] = zeros
// // ROTL32(x, y) = rotl(i64.(x||x), y)
// Value* v = b.CreateZExt(b.CreateTrunc(g.gpr_value(i.M.RS)), b.getInt64Ty());
// v = b.CreateOr(b.CreateLShr(v, 32), v);

View File

@ -172,7 +172,6 @@ XEEMITTER(bcx, 0x40000000, B )(FunctionGenerator& g, IRBuilder<>& b, I
} else {
// Decrement counter.
Value* ctr = g.ctr_value();
ctr = g.ctr_value();
ctr = b.CreateSub(ctr, b.getInt64(1));
// Ctr check.
@ -187,8 +186,8 @@ XEEMITTER(bcx, 0x40000000, B )(FunctionGenerator& g, IRBuilder<>& b, I
if (XESELECTBITS(i.B.BO, 4, 4)) {
// Ignore cond.
} else {
Value* cr = g.cr_value();
cr = b.CreateAnd(cr, XEBITMASK(i.B.BI, i.B.BI));
Value* cr = g.cr_value(i.B.BI >> 2);
cr = b.CreateAnd(cr, 1 << (i.B.BI >> 2));
if (XESELECTBITS(i.B.BO, 3, 3)) {
cond_ok = b.CreateICmpNE(cr, b.getInt64(0));
} else {
@ -256,8 +255,8 @@ XEEMITTER(bcctrx, 0x4C000420, XL )(FunctionGenerator& g, IRBuilder<>& b, I
if (XESELECTBITS(i.XL.BO, 4, 4)) {
// Ignore cond.
} else {
Value* cr = g.cr_value();
cr = b.CreateAnd(cr, XEBITMASK(i.XL.BI, i.XL.BI));
Value* cr = g.cr_value(i.XL.BI >> 2);
cr = b.CreateAnd(cr, 1 << (i.XL.BI >> 2));
if (XESELECTBITS(i.XL.BO, 3, 3)) {
cond_ok = b.CreateICmpNE(cr, b.getInt64(0));
} else {
@ -321,7 +320,6 @@ XEEMITTER(bclrx, 0x4C000020, XL )(FunctionGenerator& g, IRBuilder<>& b, I
} else {
// Decrement counter.
Value* ctr = g.ctr_value();
ctr = g.ctr_value();
ctr = b.CreateSub(ctr, b.getInt64(1));
// Ctr check.
@ -336,8 +334,8 @@ XEEMITTER(bclrx, 0x4C000020, XL )(FunctionGenerator& g, IRBuilder<>& b, I
if (XESELECTBITS(i.XL.BO, 4, 4)) {
// Ignore cond.
} else {
Value* cr = g.cr_value();
cr = b.CreateAnd(cr, XEBITMASK(i.XL.BI, i.XL.BI));
Value* cr = g.cr_value(i.XL.BI >> 2);
cr = b.CreateAnd(cr, 1 << (i.XL.BI >> 2));
if (XESELECTBITS(i.XL.BO, 3, 3)) {
cond_ok = b.CreateICmpNE(cr, b.getInt64(0));
} else {

View File

@ -61,7 +61,9 @@ FunctionGenerator::FunctionGenerator(
locals_.xer = NULL;
locals_.lr = NULL;
locals_.ctr = NULL;
locals_.cr = NULL;
for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
locals_.cr[n] = NULL;
}
for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
locals_.gpr[n] = NULL;
}
@ -95,6 +97,19 @@ FunctionBlock* FunctionGenerator::fn_block() {
return fn_block_;
}
void FunctionGenerator::PushInsertPoint() {
IRBuilder<>& b = *builder_;
insert_points_.push_back(std::pair<BasicBlock*, BasicBlock::iterator>(
b.GetInsertBlock(), b.GetInsertPoint()));
}
void FunctionGenerator::PopInsertPoint() {
IRBuilder<>& b = *builder_;
std::pair<BasicBlock*, BasicBlock::iterator> back = insert_points_.back();
b.SetInsertPoint(back.first, back.second);
insert_points_.pop_back();
}
void FunctionGenerator::GenerateBasicBlocks() {
// Always add an entry block.
BasicBlock* entry = BasicBlock::Create(*context_, "entry", gen_fn_);
@ -132,10 +147,6 @@ void FunctionGenerator::GenerateBasicBlocks() {
bbs_.insert(std::pair<uint32_t, BasicBlock*>(block->start_address, bb));
}
// Entry always jumps to the first bb.
builder_->SetInsertPoint(entry);
builder_->CreateBr(bbs_.begin()->second);
// Pass 2 fills in instructions.
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
it != fn_->blocks.end(); ++it) {
@ -153,6 +164,13 @@ void FunctionGenerator::GenerateSharedBlocks() {
Value* indirect_branch = gen_module_->getGlobalVariable("XeIndirectBranch");
// Setup initial register fill in the entry block.
// We can only do this once all the locals have been created.
b.SetInsertPoint(&gen_fn_->getEntryBlock());
FillRegisters();
// Entry always falls through to the second block.
b.CreateBr(bbs_.begin()->second);
// Setup the spill block in return.
b.SetInsertPoint(return_block_);
SpillRegisters();
@ -316,8 +334,7 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target,
IRBuilder<>& b = *builder_;
BasicBlock* next_block = GetNextBasicBlock();
BasicBlock* insert_bb = b.GetInsertBlock();
BasicBlock::iterator insert_bbi = b.GetInsertPoint();
PushInsertPoint();
// Request builds of the indirection blocks on demand.
// We can't build here because we don't know what registers will be needed
@ -325,8 +342,7 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target,
// after we are done with all user instructions.
if (!external_indirection_block_) {
// Setup locals in the entry block.
builder_->SetInsertPoint(&gen_fn_->getEntryBlock(),
gen_fn_->getEntryBlock().begin());
builder_->SetInsertPoint(&gen_fn_->getEntryBlock());
locals_.indirection_target = b.CreateAlloca(
b.getInt64Ty(), 0, "indirection_target");
locals_.indirection_cia = b.CreateAlloca(
@ -340,7 +356,7 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target,
*context_, "internal_indirection_block", gen_fn_, return_block_);
}
b.SetInsertPoint(insert_bb, insert_bbi);
PopInsertPoint();
// Check to see if the target address is within the function.
// If it is jump to that basic block. If the basic block is not found it means
@ -394,42 +410,37 @@ int FunctionGenerator::GenerateIndirectionBranch(uint32_t cia, Value* target,
Value* FunctionGenerator::LoadStateValue(uint32_t offset, Type* type,
const char* name) {
IRBuilder<>& b = *builder_;
PointerType* pointerTy = PointerType::getUnqual(type);
Function::arg_iterator args = gen_fn_->arg_begin();
Value* statePtr = args;
Value* address = builder_->CreateConstInBoundsGEP1_64(
statePtr, offset);
Value* ptr = builder_->CreatePointerCast(address, pointerTy);
return builder_->CreateLoad(ptr, name);
Value* address = b.CreateConstInBoundsGEP1_64(statePtr, offset);
Value* ptr = b.CreatePointerCast(address, pointerTy);
return b.CreateLoad(ptr, name);
}
void FunctionGenerator::StoreStateValue(uint32_t offset, Type* type,
Value* value) {
IRBuilder<>& b = *builder_;
PointerType* pointerTy = PointerType::getUnqual(type);
Function::arg_iterator args = gen_fn_->arg_begin();
Value* statePtr = args;
Value* address = builder_->CreateConstInBoundsGEP1_64(
statePtr, offset);
Value* ptr = builder_->CreatePointerCast(address, pointerTy);
builder_->CreateStore(value, ptr);
Value* address = b.CreateConstInBoundsGEP1_64(statePtr, offset);
Value* ptr = b.CreatePointerCast(address, pointerTy);
b.CreateStore(value, ptr);
}
Value* FunctionGenerator::cia_value() {
return builder_->getInt32(cia_);
}
Value* FunctionGenerator::SetupRegisterLocal(uint32_t offset, llvm::Type* type,
const char* name) {
Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) {
IRBuilder<>& b = *builder_;
// Insert into the entry block.
BasicBlock* insert_bb = builder_->GetInsertBlock();
BasicBlock::iterator insert_bbi = builder_->GetInsertPoint();
builder_->SetInsertPoint(&gen_fn_->getEntryBlock(),
gen_fn_->getEntryBlock().begin());
Value* v = builder_->CreateAlloca(type, 0, name);
builder_->CreateStore(LoadStateValue(offset, type), v);
builder_->SetInsertPoint(insert_bb, insert_bbi);
PushInsertPoint();
b.SetInsertPoint(&gen_fn_->getEntryBlock());
Value* v = b.CreateAlloca(type, 0, name);
PopInsertPoint();
return v;
}
@ -438,36 +449,51 @@ void FunctionGenerator::FillRegisters() {
// It should be called on function entry for initial setup and after any
// calls that may modify the registers.
IRBuilder<>& b = *builder_;
if (locals_.xer) {
builder_->CreateStore(LoadStateValue(
b.CreateStore(LoadStateValue(
offsetof(xe_ppc_state_t, xer),
builder_->getInt64Ty()), locals_.xer);
b.getInt64Ty()), locals_.xer);
}
if (locals_.lr) {
builder_->CreateStore(LoadStateValue(
b.CreateStore(LoadStateValue(
offsetof(xe_ppc_state_t, lr),
builder_->getInt64Ty()), locals_.lr);
b.getInt64Ty()), locals_.lr);
}
if (locals_.ctr) {
builder_->CreateStore(LoadStateValue(
b.CreateStore(LoadStateValue(
offsetof(xe_ppc_state_t, ctr),
builder_->getInt64Ty()), locals_.ctr);
b.getInt64Ty()), locals_.ctr);
}
if (locals_.cr) {
builder_->CreateStore(LoadStateValue(
offsetof(xe_ppc_state_t, cr),
builder_->getInt64Ty()), locals_.cr);
// Fill the split CR values by extracting each one from the CR.
// This could probably be done faster via an extractvalues or something.
// Perhaps we could also change it to be a vector<8*i8>.
Value* cr = NULL;
for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
Value* cr_n = locals_.cr[n];
if (!cr_n) {
continue;
}
if (!cr) {
cr = LoadStateValue(
offsetof(xe_ppc_state_t, cr),
b.getInt64Ty());
}
b.CreateStore(
b.CreateTrunc(b.CreateAnd(b.CreateLShr(cr, (28 - n * 4)), 0xF),
b.getInt8Ty()), cr_n);
}
// Note that we skip zero.
for (uint32_t n = 1; n < XECOUNT(locals_.gpr); n++) {
if (locals_.gpr[n]) {
builder_->CreateStore(LoadStateValue(
b.CreateStore(LoadStateValue(
offsetof(xe_ppc_state_t, r) + 8 * n,
builder_->getInt64Ty()), locals_.gpr[n]);
b.getInt64Ty()), locals_.gpr[n]);
}
}
}
@ -478,33 +504,49 @@ void FunctionGenerator::SpillRegisters() {
//
// TODO(benvanik): only flush if actually required, or selective flushes.
IRBuilder<>& b = *builder_;
if (locals_.xer) {
StoreStateValue(
offsetof(xe_ppc_state_t, xer),
builder_->getInt64Ty(),
builder_->CreateLoad(locals_.xer));
b.getInt64Ty(),
b.CreateLoad(locals_.xer));
}
if (locals_.lr) {
StoreStateValue(
offsetof(xe_ppc_state_t, lr),
builder_->getInt64Ty(),
builder_->CreateLoad(locals_.lr));
b.getInt64Ty(),
b.CreateLoad(locals_.lr));
}
if (locals_.ctr) {
StoreStateValue(
offsetof(xe_ppc_state_t, ctr),
builder_->getInt64Ty(),
builder_->CreateLoad(locals_.ctr));
b.getInt64Ty(),
b.CreateLoad(locals_.ctr));
}
// Stitch together all split CR values.
// TODO(benvanik): don't flush across calls?
if (locals_.cr) {
Value* cr = NULL;
for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
Value* cr_n = locals_.cr[n];
if (!cr_n) {
continue;
}
cr_n = b.CreateZExt(b.CreateLoad(cr_n), b.getInt64Ty());
if (!cr) {
cr = b.CreateShl(cr_n, n * 4);
} else {
cr = b.CreateOr(cr, b.CreateShl(cr_n, n * 4));
}
}
if (cr) {
StoreStateValue(
offsetof(xe_ppc_state_t, cr),
builder_->getInt64Ty(),
builder_->CreateLoad(locals_.cr));
b.getInt64Ty(),
cr);
}
// Note that we skip zero.
@ -513,130 +555,177 @@ void FunctionGenerator::SpillRegisters() {
if (v) {
StoreStateValue(
offsetof(xe_ppc_state_t, r) + 8 * n,
builder_->getInt64Ty(),
builder_->CreateLoad(locals_.gpr[n]));
b.getInt64Ty(),
b.CreateLoad(locals_.gpr[n]));
}
}
}
Value* FunctionGenerator::xer_value() {
if (!locals_.xer) {
locals_.xer = SetupRegisterLocal(
offsetof(xe_ppc_state_t, xer),
builder_->getInt64Ty(),
"xer");
void FunctionGenerator::setup_xer() {
IRBuilder<>& b = *builder_;
if (locals_.xer) {
return;
}
return locals_.xer;
locals_.xer = SetupLocal(b.getInt64Ty(), "xer");
}
Value* FunctionGenerator::xer_value() {
IRBuilder<>& b = *builder_;
setup_xer();
return b.CreateLoad(locals_.xer);
}
void FunctionGenerator::update_xer_value(Value* value) {
// Ensure the register is local.
xer_value();
IRBuilder<>& b = *builder_;
setup_xer();
// Extend to 64bits if needed.
if (!value->getType()->isIntegerTy(64)) {
value = builder_->CreateZExt(value, builder_->getInt64Ty());
value = b.CreateZExt(value, b.getInt64Ty());
}
builder_->CreateStore(value, locals_.xer);
b.CreateStore(value, locals_.xer);
}
void FunctionGenerator::setup_lr() {
IRBuilder<>& b = *builder_;
if (locals_.lr) {
return;
}
locals_.lr = SetupLocal(b.getInt64Ty(), "lr");
}
Value* FunctionGenerator::lr_value() {
if (!locals_.lr) {
locals_.lr = SetupRegisterLocal(
offsetof(xe_ppc_state_t, lr),
builder_->getInt64Ty(),
"lr");
}
return builder_->CreateLoad(locals_.lr);
IRBuilder<>& b = *builder_;
setup_lr();
return b.CreateLoad(locals_.lr);
}
void FunctionGenerator::update_lr_value(Value* value) {
// Ensure the register is local.
lr_value();
IRBuilder<>& b = *builder_;
setup_lr();
// Extend to 64bits if needed.
if (!value->getType()->isIntegerTy(64)) {
value = builder_->CreateZExt(value, builder_->getInt64Ty());
value = b.CreateZExt(value, b.getInt64Ty());
}
builder_->CreateStore(value, locals_.lr);
b.CreateStore(value, locals_.lr);
}
void FunctionGenerator::setup_ctr() {
IRBuilder<>& b = *builder_;
if (locals_.ctr) {
return;
}
locals_.ctr = SetupLocal(b.getInt64Ty(), "ctr");
}
Value* FunctionGenerator::ctr_value() {
if (!locals_.ctr) {
locals_.ctr = SetupRegisterLocal(
offsetof(xe_ppc_state_t, ctr),
builder_->getInt64Ty(),
"ctr");
}
return builder_->CreateLoad(locals_.ctr);
IRBuilder<>& b = *builder_;
setup_ctr();
return b.CreateLoad(locals_.ctr);
}
void FunctionGenerator::update_ctr_value(Value* value) {
// Ensure the register is local.
ctr_value();
IRBuilder<>& b = *builder_;
setup_ctr();
// Extend to 64bits if needed.
if (!value->getType()->isIntegerTy(64)) {
value = builder_->CreateZExt(value, builder_->getInt64Ty());
value = b.CreateZExt(value, b.getInt64Ty());
}
builder_->CreateStore(value, locals_.ctr);
b.CreateStore(value, locals_.ctr);
}
Value* FunctionGenerator::cr_value() {
if (!locals_.cr) {
locals_.cr = SetupRegisterLocal(
offsetof(xe_ppc_state_t, cr),
builder_->getInt64Ty(),
"cr");
void FunctionGenerator::setup_cr(uint32_t n) {
IRBuilder<>& b = *builder_;
XEASSERT(n >= 0 && n < 8);
if (locals_.cr[n]) {
return;
}
return builder_->CreateLoad(locals_.cr);
char name[32];
xesnprintfa(name, XECOUNT(name), "cr_f%d", n);
locals_.cr[n] = SetupLocal(b.getInt8Ty(), name);
}
void FunctionGenerator::update_cr_value(Value* value) {
// Ensure the register is local.
cr_value();
Value* FunctionGenerator::cr_value(uint32_t n) {
IRBuilder<>& b = *builder_;
// Extend to 64bits if needed.
if (!value->getType()->isIntegerTy(64)) {
value = builder_->CreateZExt(value, builder_->getInt64Ty());
setup_cr(n);
Value* v = b.CreateLoad(locals_.cr[n]);
v = b.CreateZExt(v, b.getInt64Ty());
return v;
}
void FunctionGenerator::update_cr_value(uint32_t n, Value* value) {
IRBuilder<>& b = *builder_;
setup_cr(n);
value = b.CreateTrunc(value, b.getInt8Ty());
b.CreateStore(value, locals_.cr[n]);
}
void FunctionGenerator::setup_gpr(uint32_t n) {
IRBuilder<>& b = *builder_;
if (locals_.gpr[n]) {
return;
}
builder_->CreateStore(value, locals_.cr);
char name[30];
xesnprintfa(name, XECOUNT(name), "gpr_r%d", n);
locals_.gpr[n] = SetupLocal(b.getInt64Ty(), name);
}
Value* FunctionGenerator::gpr_value(uint32_t n) {
IRBuilder<>& b = *builder_;
XEASSERT(n >= 0 && n < 32);
if (n == 0) {
// Always force zero to a constant - this should help LLVM.
return builder_->getInt64(0);
return b.getInt64(0);
}
if (!locals_.gpr[n]) {
char name[30];
xesnprintfa(name, XECOUNT(name), "gpr_r%d", n);
locals_.gpr[n] = SetupRegisterLocal(
offsetof(xe_ppc_state_t, r) + 8 * n,
builder_->getInt64Ty(),
name);
}
return builder_->CreateLoad(locals_.gpr[n]);
setup_gpr(n);
return b.CreateLoad(locals_.gpr[n]);
}
void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
XEASSERT(n >= 0 && n < 32);
IRBuilder<>& b = *builder_;
XEASSERT(n >= 0 && n < 32);
if (n == 0) {
// Ignore writes to zero.
return;
}
// Ensure the register is local.
gpr_value(n);
setup_gpr(n);
// Extend to 64bits if needed.
if (!value->getType()->isIntegerTy(64)) {
value = builder_->CreateZExt(value, builder_->getInt64Ty());
value = b.CreateZExt(value, b.getInt64Ty());
}
builder_->CreateStore(value, locals_.gpr[n]);
b.CreateStore(value, locals_.gpr[n]);
}
Value* FunctionGenerator::GetMembase() {
@ -649,19 +738,21 @@ Value* FunctionGenerator::memory_addr(uint32_t addr) {
}
Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) {
IRBuilder<>& b = *builder_;
Type* dataTy = NULL;
switch (size) {
case 1:
dataTy = builder_->getInt8Ty();
dataTy = b.getInt8Ty();
break;
case 2:
dataTy = builder_->getInt16Ty();
dataTy = b.getInt16Ty();
break;
case 4:
dataTy = builder_->getInt32Ty();
dataTy = b.getInt32Ty();
break;
case 8:
dataTy = builder_->getInt64Ty();
dataTy = b.getInt64Ty();
break;
default:
XEASSERTALWAYS();
@ -669,25 +760,27 @@ Value* FunctionGenerator::ReadMemory(Value* addr, uint32_t size, bool extend) {
}
PointerType* pointerTy = PointerType::getUnqual(dataTy);
Value* address = builder_->CreateInBoundsGEP(GetMembase(), addr);
Value* ptr = builder_->CreatePointerCast(address, pointerTy);
return builder_->CreateLoad(ptr);
Value* address = b.CreateInBoundsGEP(GetMembase(), addr);
Value* ptr = b.CreatePointerCast(address, pointerTy);
return b.CreateLoad(ptr);
}
void FunctionGenerator::WriteMemory(Value* addr, uint32_t size, Value* value) {
IRBuilder<>& b = *builder_;
Type* dataTy = NULL;
switch (size) {
case 1:
dataTy = builder_->getInt8Ty();
dataTy = b.getInt8Ty();
break;
case 2:
dataTy = builder_->getInt16Ty();
dataTy = b.getInt16Ty();
break;
case 4:
dataTy = builder_->getInt32Ty();
dataTy = b.getInt32Ty();
break;
case 8:
dataTy = builder_->getInt64Ty();
dataTy = b.getInt64Ty();
break;
default:
XEASSERTALWAYS();
@ -695,12 +788,12 @@ void FunctionGenerator::WriteMemory(Value* addr, uint32_t size, Value* value) {
}
PointerType* pointerTy = PointerType::getUnqual(dataTy);
Value* address = builder_->CreateInBoundsGEP(GetMembase(), addr);
Value* ptr = builder_->CreatePointerCast(address, pointerTy);
Value* address = b.CreateInBoundsGEP(GetMembase(), addr);
Value* ptr = b.CreatePointerCast(address, pointerTy);
// Truncate, if required.
if (value->getType() != dataTy) {
value = builder_->CreateTrunc(value, dataTy);
value = b.CreateTrunc(value, dataTy);
}
builder_->CreateStore(value, ptr);
b.CreateStore(value, ptr);
}