#include "VuExecutor.h" #include "VuBasicBlock.h" #include CVuExecutor::CVuExecutor(CMIPS& context, uint32 maxAddress) : CGenericMipsExecutor(context, maxAddress, BLOCK_CATEGORY_PS2_VU) { } void CVuExecutor::Reset() { m_cachedBlocks.clear(); CGenericMipsExecutor::Reset(); } BasicBlockPtr CVuExecutor::BlockFactory(CMIPS& context, uint32 begin, uint32 end) { uint32 blockSize = ((end - begin) + 4) / 4; uint32 blockSizeByte = blockSize * 4; uint32* blockMemory = reinterpret_cast(alloca(blockSizeByte)); for(uint32 address = begin; address <= end; address += 8) { uint32 index = (address - begin) / 4; uint32 addressLo = address + 0; uint32 addressHi = address + 4; uint32 opcodeLo = m_context.m_pMemoryMap->GetInstruction(addressLo); uint32 opcodeHi = m_context.m_pMemoryMap->GetInstruction(addressHi); assert((index + 0) < blockSize); blockMemory[index + 0] = opcodeLo; assert((index + 1) < blockSize); blockMemory[index + 1] = opcodeHi; } uint32 checksum = crc32(0, reinterpret_cast(blockMemory), blockSizeByte); auto equalRange = m_cachedBlocks.equal_range(checksum); for(; equalRange.first != equalRange.second; ++equalRange.first) { const auto& basicBlock(equalRange.first->second); if(basicBlock->GetEndAddress() - basicBlock->GetBeginAddress() == end - begin) { if(basicBlock->GetBeginAddress() == begin) { if(basicBlock->GetEndAddress() == end) { return basicBlock; } } auto result = std::make_shared(context, begin, end, m_blockCategory); result->CopyFunctionFrom(basicBlock); return result; } } auto result = std::make_shared(context, begin, end, m_blockCategory); result->Compile(); m_cachedBlocks.insert(std::make_pair(checksum, result)); return result; } #define VU_UPPEROP_BIT_I (0x80000000) #define VU_UPPEROP_BIT_E (0x40000000) void CVuExecutor::PartitionFunction(uint32 startAddress) { uint32 endAddress = startAddress + MAX_BLOCK_SIZE - 4; uint32 branchAddress = 0; for(uint32 address = startAddress; address < endAddress; address += 8) { uint32 addrLo = address + 0; uint32 addrHi = address + 4; uint32 lowerOp = m_context.m_pMemoryMap->GetInstruction(addrLo); uint32 upperOp = m_context.m_pMemoryMap->GetInstruction(addrHi); auto branchType = m_context.m_pArch->IsInstructionBranch(&m_context, addrLo, lowerOp); if(upperOp & VU_UPPEROP_BIT_E) { endAddress = address + 0xC; break; } else if(branchType == MIPS_BRANCH_NORMAL) { branchAddress = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, addrLo, lowerOp); endAddress = address + 0xC; break; } else if(branchType == MIPS_BRANCH_NODELAY) { //Should never happen assert(false); } } assert((endAddress - startAddress) <= MAX_BLOCK_SIZE); CreateBlock(startAddress, endAddress); auto block = static_cast(FindBlockStartingAt(startAddress)); if(block->IsLinkable()) { SetupBlockLinks(startAddress, endAddress, branchAddress); } }