Now tracking register accesses for each function.

This commit is contained in:
Ben Vanik
2013-01-29 13:07:59 -08:00
parent d1333db404
commit d3054839b7
5 changed files with 220 additions and 23 deletions

View File

@@ -845,12 +845,22 @@ XEEMITTER(dcbst, 0x7C00006C, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1;
}
XEDISASMR(dcbt, 0x7C00022C, X )(InstrData& i, InstrDisasm& d) {
d.Init("dcbt", "Data Cache Block Touch", 0);
// TODO
return d.Finish();
}
XEEMITTER(dcbt, 0x7C00022C, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
// No-op for now.
// TODO(benvanik): use @llvm.prefetch
return 0;
}
XEDISASMR(dcbtst, 0x7C0001EC, X )(InstrData& i, InstrDisasm& d) {
d.Init("dcbtst", "Data Cache Block Touch for Store", 0);
// TODO
return d.Finish();
}
XEEMITTER(dcbtst, 0x7C0001EC, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
// No-op for now.
// TODO(benvanik): use @llvm.prefetch
@@ -947,8 +957,8 @@ void RegisterEmitCategoryMemory() {
XEREGISTEREMITTER(stfsx, 0x7C00052E);
XEREGISTEREMITTER(dcbf, 0x7C0000AC);
XEREGISTEREMITTER(dcbst, 0x7C00006C);
XEREGISTEREMITTER(dcbt, 0x7C00022C);
XEREGISTEREMITTER(dcbtst, 0x7C0001EC);
XEREGISTERINSTR(dcbt, 0x7C00022C);
XEREGISTERINSTR(dcbtst, 0x7C0001EC);
XEREGISTEREMITTER(dcbz, 0x7C0007EC);
XEREGISTEREMITTER(icbi, 0x7C0007AC);
}

View File

@@ -61,6 +61,8 @@ FunctionGenerator::FunctionGenerator(
external_indirection_block_ = NULL;
bb_ = NULL;
access_bits_.Clear();
locals_.indirection_target = NULL;
locals_.indirection_cia = NULL;
@@ -146,21 +148,18 @@ void FunctionGenerator::GenerateBasicBlocks() {
return_block_ = BasicBlock::Create(*context_, "return", gen_fn_);
// Pass 1 creates all of the blocks - this way we can branch to them.
// We also track registers used so that when know which ones to fill/spill.
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
it != fn_->blocks.end(); ++it) {
FunctionBlock* block = it->second;
char name[32];
xesnprintfa(name, XECOUNT(name), "loc_%.8X", block->start_address);
BasicBlock* bb = BasicBlock::Create(*context_, name, gen_fn_);
bbs_.insert(std::pair<uint32_t, BasicBlock*>(block->start_address, bb));
PrepareBasicBlock(block);
}
// Pass 2 fills in instructions.
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
it != fn_->blocks.end(); ++it) {
FunctionBlock* block = it->second;
GenerateBasicBlock(block, GetBasicBlock(block->start_address));
GenerateBasicBlock(block);
}
// Setup the shared return/indirection/etc blocks now that we know all the
@@ -215,10 +214,49 @@ void FunctionGenerator::GenerateSharedBlocks() {
}
}
void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
BasicBlock* bb) {
void FunctionGenerator::PrepareBasicBlock(FunctionBlock* block) {
// Create the basic block that will end up getting filled during
// generation.
char name[32];
xesnprintfa(name, XECOUNT(name), "loc_%.8X", block->start_address);
BasicBlock* bb = BasicBlock::Create(*context_, name, gen_fn_);
bbs_.insert(std::pair<uint32_t, BasicBlock*>(block->start_address, bb));
// Scan and disassemble each instruction in the block to get accurate
// register access bits. In the future we could do other optimization checks
// in this pass.
// TODO(benvanik): perhaps we want to stash this for each basic block?
// We could use this for faster checking of cr/ca checks/etc.
InstrAccessBits access_bits;
uint8_t* p = xe_memory_addr(memory_, 0);
for (uint32_t ia = block->start_address; ia <= block->end_address; ia += 4) {
InstrData i;
i.address = ia;
i.code = XEGETUINT32BE(p + ia);
i.type = ppc::GetInstrType(i.code);
// Ignore unknown or ones with no disassembler fn.
if (!i.type || !i.type->disassemble) {
continue;
}
ppc::InstrDisasm d;
i.type->disassemble(i, d);
// Accumulate access bits.
access_bits.Extend(d.access_bits);
}
// Add in access bits to function access bits.
access_bits_.Extend(access_bits);
}
void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block) {
IRBuilder<>& b = *builder_;
BasicBlock* bb = GetBasicBlock(block->start_address);
XEASSERTNOTNULL(bb);
printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address);
fn_block_ = block;
@@ -268,7 +306,7 @@ void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
d.Dump(disasm);
printf(" %.8X: %.8X %s\n", ia, i.code, disasm.c_str());
} else {
printf(" %.8X: %.8X %s\n", ia, i.code, i.type->name);
printf(" %.8X: %.8X %s ???\n", ia, i.code, i.type->name);
}
// TODO(benvanik): debugging information? source/etc?