From 733fe85d372cf7c53881e9e8e26afcac8aa9550f Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sat, 26 Jan 2013 01:25:31 -0800 Subject: [PATCH] Cleaning up function registers and setting up CR. --- .../xenia/cpu/codegen/function_generator.h | 21 +- include/xenia/cpu/ppc/instr.h | 12 + src/cpu/codegen/emit_alu.cc | 28 +- src/cpu/codegen/emit_control.cc | 14 +- src/cpu/codegen/function_generator.cc | 351 +++++++++++------- 5 files changed, 267 insertions(+), 159 deletions(-) diff --git a/include/xenia/cpu/codegen/function_generator.h b/include/xenia/cpu/codegen/function_generator.h index e1bf90d57..d81d598e4 100644 --- a/include/xenia/cpu/codegen/function_generator.h +++ b/include/xenia/cpu/codegen/function_generator.h @@ -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 > + insert_points_; + std::map 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_; }; diff --git a/include/xenia/cpu/ppc/instr.h b/include/xenia/cpu/ppc/instr.h index ebdacc1e0..fab692e2c 100644 --- a/include/xenia/cpu/ppc/instr.h +++ b/include/xenia/cpu/ppc/instr.h @@ -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 { diff --git a/src/cpu/codegen/emit_alu.cc b/src/cpu/codegen/emit_alu.cc index d70e88b07..b17f43f01 100644 --- a/src/cpu/codegen/emit_alu.cc +++ b/src/cpu/codegen/emit_alu.cc @@ -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); diff --git a/src/cpu/codegen/emit_control.cc b/src/cpu/codegen/emit_control.cc index 0f2ca1882..669273f86 100644 --- a/src/cpu/codegen/emit_control.cc +++ b/src/cpu/codegen/emit_control.cc @@ -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 { diff --git a/src/cpu/codegen/function_generator.cc b/src/cpu/codegen/function_generator.cc index 433db45dd..40e286e83 100644 --- a/src/cpu/codegen/function_generator.cc +++ b/src/cpu/codegen/function_generator.cc @@ -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( + b.GetInsertBlock(), b.GetInsertPoint())); +} + +void FunctionGenerator::PopInsertPoint() { + IRBuilder<>& b = *builder_; + std::pair 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(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::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); }