mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
PPU: block info fix
This commit is contained in:
parent
dac72ff371
commit
7c418f7ea5
4 changed files with 56 additions and 62 deletions
|
@ -867,7 +867,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
add_block(_ptr.addr());
|
add_block(_ptr.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op.lk && (target == iaddr || test(pfunc->attr, ppu_attr::no_return)))
|
if (is_call && test(pfunc->attr, ppu_attr::no_return))
|
||||||
{
|
{
|
||||||
// Nothing
|
// Nothing
|
||||||
}
|
}
|
||||||
|
@ -946,8 +946,13 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
block.second = _ptr.addr() - block.first;
|
block.second = _ptr.addr() - block.first;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (op.opcode == ppu_instructions::TRAP())
|
else if (type == ppu_itype::TW || type == ppu_itype::TWI || type == ppu_itype::TD || type == ppu_itype::TDI)
|
||||||
{
|
{
|
||||||
|
if (op.opcode != ppu_instructions::TRAP())
|
||||||
|
{
|
||||||
|
add_block(_ptr.addr());
|
||||||
|
}
|
||||||
|
|
||||||
block.second = _ptr.addr() - block.first;
|
block.second = _ptr.addr() - block.first;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -790,14 +790,6 @@ static void ppu_initialize()
|
||||||
f->addAttribute(1, Attribute::NoAlias);
|
f->addAttribute(1, Attribute::NoAlias);
|
||||||
translator->AddFunction(info.addr, f);
|
translator->AddFunction(info.addr, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& b : info.blocks)
|
|
||||||
{
|
|
||||||
if (b.second)
|
|
||||||
{
|
|
||||||
translator->AddBlockInfo(b.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
legacy::FunctionPassManager pm(module.get());
|
legacy::FunctionPassManager pm(module.get());
|
||||||
|
|
|
@ -116,11 +116,6 @@ void PPUTranslator::AddFunction(u64 addr, Function* func, FunctionType* type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPUTranslator::AddBlockInfo(u64 addr)
|
|
||||||
{
|
|
||||||
m_block_info.emplace(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin, void(*custom)(PPUTranslator*))
|
Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin, void(*custom)(PPUTranslator*))
|
||||||
{
|
{
|
||||||
m_function = m_func_list[info.addr];
|
m_function = m_func_list[info.addr];
|
||||||
|
@ -225,8 +220,19 @@ Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin,
|
||||||
|
|
||||||
m_jtr = BasicBlock::Create(m_context, "__jtr", m_function);
|
m_jtr = BasicBlock::Create(m_context, "__jtr", m_function);
|
||||||
|
|
||||||
|
// Create basic blocks
|
||||||
|
for (auto&& block : info.blocks)
|
||||||
|
{
|
||||||
|
if (block.second && block.first >= m_start_addr && block.first < m_end_addr)
|
||||||
|
{
|
||||||
|
m_blocks[block.first] = BasicBlock::Create(m_context, fmt::format("loc_%llx", block.first), m_function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_blocks[m_end_addr] = BasicBlock::Create(m_context, "loc_end", m_function);
|
||||||
|
|
||||||
/* Convert each instruction to LLVM IR */
|
/* Convert each instruction to LLVM IR */
|
||||||
const auto start = GetBasicBlock(m_start_addr);
|
const auto start = m_blocks.at(m_start_addr);
|
||||||
m_ir->CreateBr(start);
|
m_ir->CreateBr(start);
|
||||||
m_ir->SetInsertPoint(start);
|
m_ir->SetInsertPoint(start);
|
||||||
|
|
||||||
|
@ -235,7 +241,7 @@ Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin,
|
||||||
// Preserve current address (m_current_addr may be changed by the decoder)
|
// Preserve current address (m_current_addr may be changed by the decoder)
|
||||||
const u64 addr = m_current_addr;
|
const u64 addr = m_current_addr;
|
||||||
|
|
||||||
if (m_current_addr == m_start_addr || info.blocks.count(m_current_addr))
|
if (m_blocks.count(m_current_addr))
|
||||||
{
|
{
|
||||||
// Bloat the beginning of each block: check state
|
// Bloat the beginning of each block: check state
|
||||||
const auto vstate = m_ir->CreateLoad(m_ir->CreateConstGEP2_32(nullptr, m_thread, 0, 1));
|
const auto vstate = m_ir->CreateLoad(m_ir->CreateConstGEP2_32(nullptr, m_thread, 0, 1));
|
||||||
|
@ -250,23 +256,29 @@ Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate opcode
|
// Translate opcode
|
||||||
const u32 op = *(m_bin = bin + (addr - m_start_addr) / sizeof(u32));
|
|
||||||
(this->*(s_ppu_decoder.decode(op)))({op});
|
|
||||||
|
|
||||||
// Calculate next address if necessary
|
|
||||||
if (m_current_addr == addr) m_current_addr += sizeof(u32);
|
|
||||||
|
|
||||||
// Get next block
|
|
||||||
const auto next = GetBasicBlock(m_current_addr);
|
|
||||||
|
|
||||||
// Finalize current block if necessary (create branch to next address)
|
|
||||||
if (!m_ir->GetInsertBlock()->getTerminator())
|
if (!m_ir->GetInsertBlock()->getTerminator())
|
||||||
{
|
{
|
||||||
m_ir->CreateBr(next);
|
const u32 op = *(m_bin = bin + (addr - m_start_addr) / sizeof(u32));
|
||||||
|
(this->*(s_ppu_decoder.decode(op)))({op});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start next block
|
// Get next address
|
||||||
m_ir->SetInsertPoint(next);
|
if (m_current_addr == addr) m_current_addr += sizeof(u32);
|
||||||
|
|
||||||
|
// Get next block if necessary
|
||||||
|
if (m_blocks.count(m_current_addr))
|
||||||
|
{
|
||||||
|
const auto next = m_blocks.at(m_current_addr);
|
||||||
|
|
||||||
|
// Finalize current block if necessary (create branch to next address)
|
||||||
|
if (!m_ir->GetInsertBlock()->getTerminator())
|
||||||
|
{
|
||||||
|
m_ir->CreateBr(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start next block
|
||||||
|
m_ir->SetInsertPoint(next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run custom IR generation function
|
// Run custom IR generation function
|
||||||
|
@ -287,22 +299,28 @@ Function* PPUTranslator::TranslateToIR(const ppu_function& info, be_t<u32>* bin,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get block entries
|
|
||||||
const std::vector<u64> cases{m_block_info.upper_bound(m_start_addr), m_block_info.lower_bound(m_end_addr)};
|
|
||||||
|
|
||||||
const auto _ctr = m_ir->CreateLoad(m_reg_ctr);
|
const auto _ctr = m_ir->CreateLoad(m_reg_ctr);
|
||||||
const auto _default = BasicBlock::Create(m_context, "__jtr.def", m_function);
|
const auto _default = BasicBlock::Create(m_context, "__jtr.def", m_function);
|
||||||
const auto _switch = m_ir->CreateSwitch(_ctr, _default, ::size32(cases));
|
const auto _switch = m_ir->CreateSwitch(_ctr, _default, ::size32(m_blocks));
|
||||||
|
|
||||||
for (const u64 addr : cases)
|
for (const auto& pair : m_blocks)
|
||||||
{
|
{
|
||||||
_switch->addCase(m_ir->getInt64(addr), GetBasicBlock(addr));
|
_switch->addCase(m_ir->getInt64(pair.first), pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ir->SetInsertPoint(_default);
|
m_ir->SetInsertPoint(_default);
|
||||||
CallFunction(0, true, _ctr);
|
CallFunction(0, true, _ctr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto&& block : *m_function)
|
||||||
|
{
|
||||||
|
if (!block.getTerminator())
|
||||||
|
{
|
||||||
|
m_ir->SetInsertPoint(&block);
|
||||||
|
m_ir->CreateUnreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return m_function;
|
return m_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,18 +412,6 @@ void PPUTranslator::UndefineVolatileRegisters()
|
||||||
//m_ir->CreateStore(m_ir->getFalse(), m_vscr_sat); // VSCR.SAT
|
//m_ir->CreateStore(m_ir->getFalse(), m_vscr_sat); // VSCR.SAT
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicBlock* PPUTranslator::GetBasicBlock(u64 address)
|
|
||||||
{
|
|
||||||
if (auto& block = m_blocks[address])
|
|
||||||
{
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return block = BasicBlock::Create(m_context, fmt::format("loc_%llx", address/* - m_start_addr*/), m_function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* PPUTranslator::Solid(Value* value)
|
Value* PPUTranslator::Solid(Value* value)
|
||||||
{
|
{
|
||||||
const u32 size = value->getType()->getPrimitiveSizeInBits();
|
const u32 size = value->getType()->getPrimitiveSizeInBits();
|
||||||
|
@ -565,7 +571,7 @@ void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
|
||||||
if (cond)
|
if (cond)
|
||||||
{
|
{
|
||||||
const auto local = BasicBlock::Create(m_context, fmt::format("loc_%llx.cond", m_current_addr/* - m_start_addr*/), m_function);
|
const auto local = BasicBlock::Create(m_context, fmt::format("loc_%llx.cond", m_current_addr/* - m_start_addr*/), m_function);
|
||||||
m_ir->CreateCondBr(cond, local, GetBasicBlock(m_current_addr + 4), hint);
|
m_ir->CreateCondBr(cond, local, m_blocks.at(m_current_addr + 4), hint);
|
||||||
m_ir->SetInsertPoint(local);
|
m_ir->SetInsertPoint(local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1761,12 +1767,12 @@ void PPUTranslator::BC(ppu_opcode_t op)
|
||||||
}
|
}
|
||||||
else if (cond)
|
else if (cond)
|
||||||
{
|
{
|
||||||
m_ir->CreateCondBr(cond, GetBasicBlock(target), GetBasicBlock(m_current_addr + 4), CheckBranchProbability(op.bo));
|
m_ir->CreateCondBr(cond, m_blocks.at(target), m_blocks.at(m_current_addr + 4), CheckBranchProbability(op.bo));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ir->CreateBr(GetBasicBlock(target));
|
m_ir->CreateBr(m_blocks.at(target));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1809,7 +1815,7 @@ void PPUTranslator::B(ppu_opcode_t op)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ir->CreateBr(GetBasicBlock(target));
|
m_ir->CreateBr(m_blocks.at(target));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1927,7 +1933,7 @@ void PPUTranslator::BCCTR(ppu_opcode_t op)
|
||||||
|
|
||||||
for (const u64 target : targets)
|
for (const u64 target : targets)
|
||||||
{
|
{
|
||||||
_switch->addCase(m_ir->getInt64(target), GetBasicBlock(target));
|
_switch->addCase(m_ir->getInt64(target), m_blocks.at(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ir->SetInsertPoint(_default);
|
m_ir->SetInsertPoint(_default);
|
||||||
|
|
|
@ -139,9 +139,6 @@ class PPUTranslator final //: public CPUTranslator
|
||||||
// Basic blocks for current function
|
// Basic blocks for current function
|
||||||
std::unordered_map<u64, llvm::BasicBlock*> m_blocks;
|
std::unordered_map<u64, llvm::BasicBlock*> m_blocks;
|
||||||
|
|
||||||
// Supplementary block info for all functions
|
|
||||||
std::set<u64> m_block_info;
|
|
||||||
|
|
||||||
// JT resolver block
|
// JT resolver block
|
||||||
llvm::BasicBlock* m_jtr;
|
llvm::BasicBlock* m_jtr;
|
||||||
|
|
||||||
|
@ -239,9 +236,6 @@ public:
|
||||||
// Set some registers to undef (after function call)
|
// Set some registers to undef (after function call)
|
||||||
void UndefineVolatileRegisters();
|
void UndefineVolatileRegisters();
|
||||||
|
|
||||||
// Get the basic block for the specified address
|
|
||||||
llvm::BasicBlock* GetBasicBlock(u64 addr);
|
|
||||||
|
|
||||||
// Load gpr
|
// Load gpr
|
||||||
llvm::Value* GetGpr(u32 r, u32 num_bits = 64);
|
llvm::Value* GetGpr(u32 r, u32 num_bits = 64);
|
||||||
|
|
||||||
|
@ -447,9 +441,6 @@ public:
|
||||||
// Add function
|
// Add function
|
||||||
void AddFunction(u64 addr, llvm::Function* func, llvm::FunctionType* type = nullptr);
|
void AddFunction(u64 addr, llvm::Function* func, llvm::FunctionType* type = nullptr);
|
||||||
|
|
||||||
// Add block entry hint (not essential)
|
|
||||||
void AddBlockInfo(u64 addr);
|
|
||||||
|
|
||||||
// Parses PPU opcodes and translate them into LLVM IR
|
// Parses PPU opcodes and translate them into LLVM IR
|
||||||
llvm::Function* TranslateToIR(const ppu_function& info, be_t<u32>* bin, void(*custom)(PPUTranslator*) = nullptr);
|
llvm::Function* TranslateToIR(const ppu_function& info, be_t<u32>* bin, void(*custom)(PPUTranslator*) = nullptr);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue