mirror of
https://github.com/libretro/Play-.git
synced 2024-12-13 11:35:30 +00:00
Added new way to search for blocks in the compiled block list which is O(1).
Removed some useless params in MIPS constructor. Removed the need for the _PSX preprocessor def. git-svn-id: http://svn.purei.org/purei/trunk@860 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
937e5870ff
commit
b1afb8abee
@ -12,7 +12,7 @@ const char* CMIPS::m_sGPRName[] =
|
||||
"T8", "T9", "K0", "K1", "GP", "SP", "FP", "RA"
|
||||
};
|
||||
|
||||
CMIPS::CMIPS(MEMORYMAP_ENDIANESS nEnd, uint32 nExecStart, uint32 nExecEnd)
|
||||
CMIPS::CMIPS(MEMORYMAP_ENDIANESS nEnd)
|
||||
: m_pAddrTranslator(NULL)
|
||||
, m_pArch(NULL)
|
||||
{
|
||||
@ -54,12 +54,12 @@ void CMIPS::Reset()
|
||||
|
||||
void CMIPS::ToggleBreakpoint(uint32 address)
|
||||
{
|
||||
if(m_breakpoints.find(address) != m_breakpoints.end())
|
||||
if(m_breakpoints.find(address) != m_breakpoints.end())
|
||||
{
|
||||
m_breakpoints.erase(address);
|
||||
m_breakpoints.erase(address);
|
||||
return;
|
||||
}
|
||||
m_breakpoints.insert(address);
|
||||
m_breakpoints.insert(address);
|
||||
}
|
||||
|
||||
long CMIPS::GetBranch(uint16 nData)
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
struct REGISTER_PIPELINE
|
||||
{
|
||||
uint32 counter;
|
||||
uint32 heldValue;
|
||||
uint32 counter;
|
||||
uint32 heldValue;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -99,12 +99,12 @@ __attribute__((aligned(16)))
|
||||
class CMIPS
|
||||
{
|
||||
public:
|
||||
typedef unsigned int (*TickFunctionType)(unsigned int, CMIPS*);
|
||||
typedef void (*SysCallHandlerType)(CMIPS*);
|
||||
typedef uint32 (*AddressTranslator)(CMIPS*, uint32, uint32);
|
||||
typedef std::set<uint32> BreakpointSet;
|
||||
typedef unsigned int (*TickFunctionType)(unsigned int, CMIPS*);
|
||||
typedef void (*SysCallHandlerType)(CMIPS*);
|
||||
typedef uint32 (*AddressTranslator)(CMIPS*, uint32, uint32);
|
||||
typedef std::set<uint32> BreakpointSet;
|
||||
|
||||
CMIPS(MEMORYMAP_ENDIANESS, uint32, uint32);
|
||||
CMIPS(MEMORYMAP_ENDIANESS);
|
||||
~CMIPS();
|
||||
void ToggleBreakpoint(uint32);
|
||||
bool MustBreak();
|
||||
@ -124,7 +124,7 @@ public:
|
||||
CMIPSArchitecture* m_pArch;
|
||||
CMIPSCoprocessor* m_pCOP[4];
|
||||
CMemoryMap* m_pMemoryMap;
|
||||
BreakpointSet m_breakpoints;
|
||||
BreakpointSet m_breakpoints;
|
||||
|
||||
CMIPSAnalysis* m_pAnalysis;
|
||||
CMIPSTags m_Comments;
|
||||
|
@ -1,14 +1,37 @@
|
||||
#include "MipsExecutor.h"
|
||||
|
||||
CMipsExecutor::CMipsExecutor(CMIPS& context) :
|
||||
m_context(context)
|
||||
CMipsExecutor::CMipsExecutor(CMIPS& context, uint32 maxAddress)
|
||||
: m_context(context)
|
||||
, m_subTableCount(0)
|
||||
{
|
||||
|
||||
if(maxAddress < 0x10000)
|
||||
{
|
||||
maxAddress = 0x10000;
|
||||
}
|
||||
assert((maxAddress & 0xFFFF) == 0);
|
||||
if(maxAddress == 0)
|
||||
{
|
||||
m_subTableCount = 0x10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_subTableCount = maxAddress / 0x10000;
|
||||
}
|
||||
m_blockTable = new CBasicBlock**[m_subTableCount];
|
||||
memset(m_blockTable, 0, sizeof(CBasicBlock**) * m_subTableCount);
|
||||
}
|
||||
|
||||
CMipsExecutor::~CMipsExecutor()
|
||||
{
|
||||
|
||||
for(unsigned int i = 0; i < m_subTableCount; i++)
|
||||
{
|
||||
CBasicBlock** subTable = m_blockTable[i];
|
||||
if(subTable != NULL)
|
||||
{
|
||||
delete [] subTable;
|
||||
}
|
||||
}
|
||||
delete [] m_blockTable;
|
||||
}
|
||||
|
||||
void CMipsExecutor::Reset()
|
||||
@ -18,215 +41,178 @@ void CMipsExecutor::Reset()
|
||||
|
||||
void CMipsExecutor::ClearActiveBlocks()
|
||||
{
|
||||
for(BlockList::iterator blockIterator(m_blocks.begin());
|
||||
blockIterator != m_blocks.end(); blockIterator++)
|
||||
{
|
||||
//Clear the branch hint in case block isn't deleted.
|
||||
BasicBlockPtr& currBlock = (*blockIterator);
|
||||
currBlock->SetBranchHint(BasicBlockPtr());
|
||||
}
|
||||
for(unsigned int i = 0; i < m_subTableCount; i++)
|
||||
{
|
||||
CBasicBlock** subTable = m_blockTable[i];
|
||||
if(subTable != NULL)
|
||||
{
|
||||
delete [] subTable;
|
||||
m_blockTable[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m_blocks.clear();
|
||||
m_blockBegin.clear();
|
||||
m_blockEnd.clear();
|
||||
}
|
||||
|
||||
int CMipsExecutor::Execute(int cycles)
|
||||
{
|
||||
BasicBlockPtr block;
|
||||
CBasicBlock* block(NULL);
|
||||
#ifdef DEBUGGER_INCLUDED
|
||||
bool firstExec = true;
|
||||
#endif
|
||||
while(cycles > 0)
|
||||
{
|
||||
while(cycles > 0)
|
||||
{
|
||||
#ifdef DEBUGGER_INCLUDED
|
||||
if(!firstExec && MustBreak()) break;
|
||||
if(!firstExec && MustBreak()) break;
|
||||
firstExec = false;
|
||||
#endif
|
||||
#ifdef _PSX
|
||||
uint32 address = m_context.m_pAddrTranslator(&m_context, 0, m_context.m_State.nPC);
|
||||
#else
|
||||
uint32 address = m_context.m_State.nPC;
|
||||
#endif
|
||||
if(!block || address != block->GetBeginAddress())
|
||||
{
|
||||
BasicBlockPtr prevBlock = block;
|
||||
//Check if we can use the hint instead of looking through the map
|
||||
if(prevBlock)
|
||||
{
|
||||
block = prevBlock->GetBranchHint();
|
||||
}
|
||||
if(block == NULL || address != block->GetBeginAddress())
|
||||
{
|
||||
block = FindBlockStartingAt(address);
|
||||
if(block == NULL)
|
||||
{
|
||||
//We need to partition the space and compile the blocks
|
||||
PartitionFunction(address);
|
||||
uint32 address = m_context.m_pAddrTranslator(&m_context, 0, m_context.m_State.nPC);
|
||||
if(!block || address != block->GetBeginAddress())
|
||||
{
|
||||
block = FindBlockStartingAt(address);
|
||||
if(block == NULL)
|
||||
{
|
||||
//We need to partition the space and compile the blocks
|
||||
PartitionFunction(address);
|
||||
block = FindBlockStartingAt(address);
|
||||
if(block == NULL)
|
||||
{
|
||||
throw std::runtime_error("Couldn't create block starting at address.");
|
||||
}
|
||||
}
|
||||
if(!block->IsCompiled())
|
||||
{
|
||||
block->Compile();
|
||||
}
|
||||
}
|
||||
else if(block != NULL)
|
||||
{
|
||||
block->SetSelfLoopCount(block->GetSelfLoopCount() + 1);
|
||||
}
|
||||
|
||||
//Invalidate prevBlock because it might have been deleted by PartitionFunction
|
||||
prevBlock = NULL;
|
||||
|
||||
block = FindBlockStartingAt(address);
|
||||
if(block == NULL)
|
||||
{
|
||||
throw std::runtime_error("Couldn't create block starting at address.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(prevBlock != NULL)
|
||||
{
|
||||
prevBlock->SetBranchHint(block);
|
||||
}
|
||||
if(!block->IsCompiled())
|
||||
{
|
||||
block->Compile();
|
||||
}
|
||||
}
|
||||
else if(block != NULL)
|
||||
{
|
||||
block->SetSelfLoopCount(block->GetSelfLoopCount() + 1);
|
||||
}
|
||||
|
||||
cycles -= block->Execute();
|
||||
if(m_context.m_State.nHasException) break;
|
||||
}
|
||||
return cycles;
|
||||
cycles -= block->Execute();
|
||||
if(m_context.m_State.nHasException) break;
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
bool CMipsExecutor::MustBreak() const
|
||||
{
|
||||
#ifdef DEBUGGER_INCLUDED
|
||||
#ifdef _PSX
|
||||
uint32 currentPc = m_context.m_pAddrTranslator(&m_context, 0, m_context.m_State.nPC);
|
||||
#else
|
||||
uint32 currentPc = m_context.m_State.nPC;
|
||||
uint32 currentPc = m_context.m_pAddrTranslator(&m_context, 0, m_context.m_State.nPC);
|
||||
BasicBlockPtr block = FindBlockAt(currentPc);
|
||||
for(CMIPS::BreakpointSet::const_iterator breakPointIterator(m_context.m_breakpoints.begin());
|
||||
breakPointIterator != m_context.m_breakpoints.end(); breakPointIterator++)
|
||||
{
|
||||
uint32 breakPointAddress = *breakPointIterator;
|
||||
if(currentPc == breakPointAddress) return true;
|
||||
if(block != NULL)
|
||||
{
|
||||
if(breakPointAddress >= block->GetBeginAddress() && breakPointAddress <= block->GetEndAddress()) return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
BasicBlockPtr block = FindBlockAt(currentPc);
|
||||
for(CMIPS::BreakpointSet::const_iterator breakPointIterator(m_context.m_breakpoints.begin());
|
||||
breakPointIterator != m_context.m_breakpoints.end(); breakPointIterator++)
|
||||
{
|
||||
uint32 breakPointAddress = *breakPointIterator;
|
||||
if(currentPc == breakPointAddress) return true;
|
||||
if(block != NULL)
|
||||
{
|
||||
if(breakPointAddress >= block->GetBeginAddress() && breakPointAddress <= block->GetEndAddress()) return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicBlockPtr CMipsExecutor::FindBlockAt(uint32 address) const
|
||||
CBasicBlock* CMipsExecutor::FindBlockAt(uint32 address) const
|
||||
{
|
||||
BlockBeginMap::const_iterator beginIterator = m_blockBegin.lower_bound(address);
|
||||
if(beginIterator == m_blockBegin.end()) return NULL;
|
||||
|
||||
{
|
||||
const BasicBlockPtr& block = beginIterator->second;
|
||||
if(
|
||||
address >= block->GetBeginAddress() &&
|
||||
address <= block->GetEndAddress())
|
||||
{
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
BlockEndMap::const_iterator endIterator = m_blockEnd.lower_bound(address);
|
||||
if(endIterator == m_blockEnd.end()) return NULL;
|
||||
|
||||
{
|
||||
const BasicBlockPtr& block = endIterator->second;
|
||||
if(
|
||||
address >= block->GetBeginAddress() &&
|
||||
address <= block->GetEndAddress())
|
||||
{
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
if(beginIterator->second != endIterator->second)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return beginIterator->second;
|
||||
uint32 hiAddress = address >> 16;
|
||||
uint32 loAddress = address & 0xFFFF;
|
||||
assert(hiAddress < m_subTableCount);
|
||||
CBasicBlock**& subTable = m_blockTable[hiAddress];
|
||||
if(subTable == NULL) return NULL;
|
||||
CBasicBlock* result = subTable[loAddress / 4];
|
||||
return result;
|
||||
}
|
||||
|
||||
BasicBlockPtr CMipsExecutor::FindBlockStartingAt(uint32 address)
|
||||
CBasicBlock* CMipsExecutor::FindBlockStartingAt(uint32 address) const
|
||||
{
|
||||
BlockBeginMap::const_iterator beginIterator = m_blockBegin.find(address);
|
||||
if(beginIterator == m_blockBegin.end()) return NULL;
|
||||
return beginIterator->second;
|
||||
uint32 hiAddress = address >> 16;
|
||||
uint32 loAddress = address & 0xFFFF;
|
||||
assert(hiAddress < m_subTableCount);
|
||||
CBasicBlock**& subTable = m_blockTable[hiAddress];
|
||||
if(subTable == NULL) return NULL;
|
||||
CBasicBlock* result = subTable[loAddress / 4];
|
||||
if((address != 0) && (FindBlockAt(address - 4) == result))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CMipsExecutor::CreateBlock(uint32 start, uint32 end)
|
||||
{
|
||||
{
|
||||
BasicBlockPtr block = FindBlockAt(start);
|
||||
if(block)
|
||||
{
|
||||
//If the block starts and ends at the same place, block already exists and doesn't need
|
||||
//to be re-created
|
||||
uint32 otherBegin = block->GetBeginAddress();
|
||||
uint32 otherEnd = block->GetEndAddress();
|
||||
if((otherBegin == start) && (otherEnd == end))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(otherEnd == end)
|
||||
{
|
||||
//Repartition the existing block if end of both blocks are the same
|
||||
DeleteBlock(block);
|
||||
CreateBlock(otherBegin, start - 4);
|
||||
assert(FindBlockAt(start) == NULL);
|
||||
}
|
||||
else if(otherBegin == start)
|
||||
{
|
||||
DeleteBlock(block);
|
||||
CreateBlock(end + 4, otherEnd);
|
||||
assert(FindBlockAt(end) == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Delete the currently existing block otherwise
|
||||
printf("MipsExecutor: Warning. Deleting block at %0.8X.\r\n", block->GetEndAddress());
|
||||
DeleteBlock(block);
|
||||
}
|
||||
}
|
||||
assert(m_blockBegin.find(start) == m_blockBegin.end());
|
||||
assert(m_blockEnd.find(end) == m_blockEnd.end());
|
||||
}
|
||||
assert(FindBlockAt(end) == NULL);
|
||||
{
|
||||
BasicBlockPtr block = BlockFactory(m_context, start, end);
|
||||
m_blocks.push_back(block);
|
||||
m_blockBegin[start] = block;
|
||||
m_blockEnd[end] = block;
|
||||
}
|
||||
assert(m_blocks.size() == m_blockBegin.size());
|
||||
assert(m_blockBegin.size() == m_blockEnd.size());
|
||||
{
|
||||
CBasicBlock* block = FindBlockAt(start);
|
||||
if(block)
|
||||
{
|
||||
//If the block starts and ends at the same place, block already exists and doesn't need
|
||||
//to be re-created
|
||||
uint32 otherBegin = block->GetBeginAddress();
|
||||
uint32 otherEnd = block->GetEndAddress();
|
||||
if((otherBegin == start) && (otherEnd == end))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(otherEnd == end)
|
||||
{
|
||||
//Repartition the existing block if end of both blocks are the same
|
||||
DeleteBlock(block);
|
||||
CreateBlock(otherBegin, start - 4);
|
||||
assert(FindBlockAt(start) == NULL);
|
||||
}
|
||||
else if(otherBegin == start)
|
||||
{
|
||||
DeleteBlock(block);
|
||||
CreateBlock(end + 4, otherEnd);
|
||||
assert(FindBlockAt(end) == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Delete the currently existing block otherwise
|
||||
printf("MipsExecutor: Warning. Deleting block at %0.8X.\r\n", block->GetEndAddress());
|
||||
DeleteBlock(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(FindBlockAt(end) == NULL);
|
||||
{
|
||||
BasicBlockPtr block = BlockFactory(m_context, start, end);
|
||||
m_blocks.push_back(block);
|
||||
for(uint32 address = block->GetBeginAddress(); address <= block->GetEndAddress(); address += 4)
|
||||
{
|
||||
uint32 hiAddress = address >> 16;
|
||||
uint32 loAddress = address & 0xFFFF;
|
||||
assert(hiAddress < m_subTableCount);
|
||||
CBasicBlock**& subTable = m_blockTable[hiAddress];
|
||||
if(subTable == NULL)
|
||||
{
|
||||
const uint32 subTableSize = 0x10000 / 4;
|
||||
subTable = new CBasicBlock*[subTableSize];
|
||||
memset(subTable, 0, sizeof(CBasicBlock*) * subTableSize);
|
||||
}
|
||||
assert(subTable[loAddress / 4] == NULL);
|
||||
subTable[loAddress / 4] = block.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMipsExecutor::DeleteBlock(const BasicBlockPtr& block)
|
||||
void CMipsExecutor::DeleteBlock(CBasicBlock* block)
|
||||
{
|
||||
//Clear any hints that point to this block
|
||||
for(BlockList::iterator blockIterator(m_blocks.begin());
|
||||
blockIterator != m_blocks.end(); blockIterator++)
|
||||
{
|
||||
BasicBlockPtr& currBlock = (*blockIterator);
|
||||
if(currBlock->GetBranchHint() == block)
|
||||
{
|
||||
currBlock->SetBranchHint(NULL);
|
||||
}
|
||||
}
|
||||
for(uint32 address = block->GetBeginAddress(); address <= block->GetEndAddress(); address += 4)
|
||||
{
|
||||
uint32 hiAddress = address >> 16;
|
||||
uint32 loAddress = address & 0xFFFF;
|
||||
assert(hiAddress < m_subTableCount);
|
||||
CBasicBlock**& subTable = m_blockTable[hiAddress];
|
||||
assert(subTable != NULL);
|
||||
assert(subTable[loAddress / 4] != NULL);
|
||||
subTable[loAddress / 4] = NULL;
|
||||
}
|
||||
|
||||
//Remove block from our lists
|
||||
m_blocks.remove(block);
|
||||
m_blockBegin.erase(block->GetBeginAddress());
|
||||
m_blockEnd.erase(block->GetEndAddress());
|
||||
assert(m_blocks.size() == m_blockBegin.size());
|
||||
assert(m_blockBegin.size() == m_blockEnd.size());
|
||||
//Remove block from our lists
|
||||
m_blocks.remove(block);
|
||||
}
|
||||
|
||||
BasicBlockPtr CMipsExecutor::BlockFactory(CMIPS& context, uint32 start, uint32 end)
|
||||
@ -236,65 +222,65 @@ BasicBlockPtr CMipsExecutor::BlockFactory(CMIPS& context, uint32 start, uint32 e
|
||||
|
||||
void CMipsExecutor::PartitionFunction(uint32 functionAddress)
|
||||
{
|
||||
typedef std::set<uint32> PartitionPointSet;
|
||||
uint32 endAddress = 0;
|
||||
PartitionPointSet partitionPoints;
|
||||
typedef std::set<uint32> PartitionPointSet;
|
||||
uint32 endAddress = 0;
|
||||
PartitionPointSet partitionPoints;
|
||||
|
||||
//Insert begin point
|
||||
partitionPoints.insert(functionAddress);
|
||||
//Insert begin point
|
||||
partitionPoints.insert(functionAddress);
|
||||
|
||||
//Find the end
|
||||
for(uint32 address = functionAddress; ; address += 4)
|
||||
{
|
||||
//Probably going too far...
|
||||
if((address - functionAddress) > 0x10000)
|
||||
{
|
||||
printf("MipsExecutor: Warning. Found no JR after a big distance.\r\n");
|
||||
endAddress = address;
|
||||
partitionPoints.insert(endAddress);
|
||||
break;
|
||||
}
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
if(opcode == 0x03E00008)
|
||||
{
|
||||
//+4 for delay slot
|
||||
endAddress = address + 4;
|
||||
partitionPoints.insert(endAddress + 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Find the end
|
||||
for(uint32 address = functionAddress; ; address += 4)
|
||||
{
|
||||
//Probably going too far...
|
||||
if((address - functionAddress) > 0x10000)
|
||||
{
|
||||
printf("MipsExecutor: Warning. Found no JR after a big distance.\r\n");
|
||||
endAddress = address;
|
||||
partitionPoints.insert(endAddress);
|
||||
break;
|
||||
}
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
if(opcode == 0x03E00008)
|
||||
{
|
||||
//+4 for delay slot
|
||||
endAddress = address + 4;
|
||||
partitionPoints.insert(endAddress + 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Find partition points within the function
|
||||
for(uint32 address = functionAddress; address <= endAddress; address += 4)
|
||||
{
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
//Find partition points within the function
|
||||
for(uint32 address = functionAddress; address <= endAddress; address += 4)
|
||||
{
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
MIPS_BRANCH_TYPE branchType = m_context.m_pArch->IsInstructionBranch(&m_context, address, opcode);
|
||||
if(branchType == MIPS_BRANCH_NORMAL)
|
||||
{
|
||||
partitionPoints.insert(address + 8);
|
||||
uint32 target = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, address, opcode);
|
||||
if(target > functionAddress && target < endAddress)
|
||||
{
|
||||
partitionPoints.insert(target);
|
||||
}
|
||||
}
|
||||
if(branchType == MIPS_BRANCH_NORMAL)
|
||||
{
|
||||
partitionPoints.insert(address + 8);
|
||||
uint32 target = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, address, opcode);
|
||||
if(target > functionAddress && target < endAddress)
|
||||
{
|
||||
partitionPoints.insert(target);
|
||||
}
|
||||
}
|
||||
else if(branchType == MIPS_BRANCH_NODELAY)
|
||||
{
|
||||
partitionPoints.insert(address + 4);
|
||||
}
|
||||
//Check if there's a block already exising that this address
|
||||
if(address != endAddress)
|
||||
{
|
||||
BasicBlockPtr possibleBlock = FindBlockStartingAt(address);
|
||||
if(possibleBlock)
|
||||
{
|
||||
//assert(possibleBlock->GetEndAddress() <= endAddress);
|
||||
//Add its beginning and end in the partition points
|
||||
partitionPoints.insert(possibleBlock->GetBeginAddress());
|
||||
partitionPoints.insert(possibleBlock->GetEndAddress() + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Check if there's a block already exising that this address
|
||||
if(address != endAddress)
|
||||
{
|
||||
BasicBlockPtr possibleBlock = FindBlockStartingAt(address);
|
||||
if(possibleBlock)
|
||||
{
|
||||
//assert(possibleBlock->GetEndAddress() <= endAddress);
|
||||
//Add its beginning and end in the partition points
|
||||
partitionPoints.insert(possibleBlock->GetBeginAddress());
|
||||
partitionPoints.insert(possibleBlock->GetEndAddress() + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if blocks are too big
|
||||
{
|
||||
|
@ -8,29 +8,28 @@
|
||||
class CMipsExecutor
|
||||
{
|
||||
public:
|
||||
CMipsExecutor(CMIPS&);
|
||||
CMipsExecutor(CMIPS&, uint32);
|
||||
virtual ~CMipsExecutor();
|
||||
int Execute(int);
|
||||
bool MustBreak() const;
|
||||
BasicBlockPtr FindBlockAt(uint32) const;
|
||||
BasicBlockPtr FindBlockStartingAt(uint32);
|
||||
void DeleteBlock(const BasicBlockPtr&);
|
||||
CBasicBlock* FindBlockAt(uint32) const;
|
||||
CBasicBlock* FindBlockStartingAt(uint32) const;
|
||||
void DeleteBlock(CBasicBlock*);
|
||||
virtual void Reset();
|
||||
void ClearActiveBlocks();
|
||||
|
||||
protected:
|
||||
typedef std::list<BasicBlockPtr> BlockList;
|
||||
typedef std::map<uint32, BasicBlockPtr, std::greater<uint32> > BlockBeginMap;
|
||||
typedef std::map<uint32, BasicBlockPtr> BlockEndMap;
|
||||
|
||||
void CreateBlock(uint32, uint32);
|
||||
virtual BasicBlockPtr BlockFactory(CMIPS&, uint32, uint32);
|
||||
virtual void PartitionFunction(uint32);
|
||||
|
||||
BlockList m_blocks;
|
||||
BlockBeginMap m_blockBegin;
|
||||
BlockEndMap m_blockEnd;
|
||||
CMIPS& m_context;
|
||||
|
||||
CBasicBlock*** m_blockTable;
|
||||
uint32 m_subTableCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -80,10 +80,10 @@ CPS2VM::CPS2VM()
|
||||
, m_pVUMem1(new uint8[PS2::VUMEM1SIZE])
|
||||
, m_pMicroMem1(new uint8[PS2::MICROMEM1SIZE])
|
||||
, m_thread(NULL)
|
||||
, m_EE(MEMORYMAP_ENDIAN_LSBF, 0x00000000, 0x20000000)
|
||||
, m_VU0(MEMORYMAP_ENDIAN_LSBF, 0x00000000, 0x00008000)
|
||||
, m_VU1(MEMORYMAP_ENDIAN_LSBF, 0x00000000, 0x00008000)
|
||||
, m_executor(m_EE)
|
||||
, m_EE(MEMORYMAP_ENDIAN_LSBF)
|
||||
, m_VU0(MEMORYMAP_ENDIAN_LSBF)
|
||||
, m_VU1(MEMORYMAP_ENDIAN_LSBF)
|
||||
, m_executor(m_EE, 0x20000000)
|
||||
, m_nStatus(PAUSED)
|
||||
, m_nEnd(false)
|
||||
, m_pGS(NULL)
|
||||
|
@ -2,8 +2,10 @@
|
||||
#include "VuBasicBlock.h"
|
||||
#include <zlib.h>
|
||||
|
||||
static const uint32 c_vuMaxAddress = 0x4000;
|
||||
|
||||
CVuExecutor::CVuExecutor(CMIPS& context) :
|
||||
CMipsExecutor(context)
|
||||
CMipsExecutor(context, c_vuMaxAddress)
|
||||
{
|
||||
|
||||
}
|
||||
@ -62,90 +64,89 @@ BasicBlockPtr CVuExecutor::BlockFactory(CMIPS& context, uint32 begin, uint32 end
|
||||
|
||||
void CVuExecutor::PartitionFunction(uint32 functionAddress)
|
||||
{
|
||||
const uint32 vuMaxAddress = 0x4000;
|
||||
typedef std::set<uint32> PartitionPointSet;
|
||||
uint32 endAddress = 0;
|
||||
PartitionPointSet partitionPoints;
|
||||
typedef std::set<uint32> PartitionPointSet;
|
||||
uint32 endAddress = 0;
|
||||
PartitionPointSet partitionPoints;
|
||||
|
||||
//Insert begin point
|
||||
partitionPoints.insert(functionAddress);
|
||||
//Insert begin point
|
||||
partitionPoints.insert(functionAddress);
|
||||
|
||||
//Find the end
|
||||
for(uint32 address = functionAddress; ; address += 4)
|
||||
{
|
||||
//Probably going too far...
|
||||
if(address >= vuMaxAddress)
|
||||
{
|
||||
endAddress = address;
|
||||
partitionPoints.insert(endAddress);
|
||||
break;
|
||||
}
|
||||
//Find the end
|
||||
for(uint32 address = functionAddress; ; address += 4)
|
||||
{
|
||||
//Probably going too far...
|
||||
if(address >= c_vuMaxAddress)
|
||||
{
|
||||
endAddress = address;
|
||||
partitionPoints.insert(endAddress);
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
//If we find the E bit in an upper instruction
|
||||
if((address & 0x04) && (opcode & 0x40000000))
|
||||
{
|
||||
endAddress = address + 8;
|
||||
partitionPoints.insert(endAddress + 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
//If we find the E bit in an upper instruction
|
||||
if((address & 0x04) && (opcode & 0x40000000))
|
||||
{
|
||||
endAddress = address + 8;
|
||||
partitionPoints.insert(endAddress + 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Find partition points within the function
|
||||
for(uint32 address = functionAddress; address <= endAddress; address += 4)
|
||||
{
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
MIPS_BRANCH_TYPE branchType = m_context.m_pArch->IsInstructionBranch(&m_context, address, opcode);
|
||||
if(branchType == MIPS_BRANCH_NORMAL)
|
||||
{
|
||||
assert((address & 0x07) == 0x00);
|
||||
partitionPoints.insert(address + 0x10);
|
||||
uint32 target = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, address, opcode);
|
||||
if(target > functionAddress && target < endAddress)
|
||||
{
|
||||
assert((target & 0x07) == 0x00);
|
||||
partitionPoints.insert(target);
|
||||
}
|
||||
}
|
||||
//Find partition points within the function
|
||||
for(uint32 address = functionAddress; address <= endAddress; address += 4)
|
||||
{
|
||||
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
|
||||
MIPS_BRANCH_TYPE branchType = m_context.m_pArch->IsInstructionBranch(&m_context, address, opcode);
|
||||
if(branchType == MIPS_BRANCH_NORMAL)
|
||||
{
|
||||
assert((address & 0x07) == 0x00);
|
||||
partitionPoints.insert(address + 0x10);
|
||||
uint32 target = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, address, opcode);
|
||||
if(target > functionAddress && target < endAddress)
|
||||
{
|
||||
assert((target & 0x07) == 0x00);
|
||||
partitionPoints.insert(target);
|
||||
}
|
||||
}
|
||||
|
||||
//Check if there's a block already exising that this address
|
||||
if(address != endAddress)
|
||||
{
|
||||
BasicBlockPtr possibleBlock = FindBlockStartingAt(address);
|
||||
if(possibleBlock != NULL)
|
||||
{
|
||||
assert(possibleBlock->GetEndAddress() <= endAddress);
|
||||
//Add its beginning and end in the partition points
|
||||
partitionPoints.insert(possibleBlock->GetBeginAddress());
|
||||
partitionPoints.insert(possibleBlock->GetEndAddress() + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Check if there's a block already exising that this address
|
||||
if(address != endAddress)
|
||||
{
|
||||
BasicBlockPtr possibleBlock = FindBlockStartingAt(address);
|
||||
if(possibleBlock != NULL)
|
||||
{
|
||||
assert(possibleBlock->GetEndAddress() <= endAddress);
|
||||
//Add its beginning and end in the partition points
|
||||
partitionPoints.insert(possibleBlock->GetBeginAddress());
|
||||
partitionPoints.insert(possibleBlock->GetEndAddress() + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 currentPoint = MIPS_INVALID_PC;
|
||||
for(PartitionPointSet::const_iterator pointIterator(partitionPoints.begin());
|
||||
pointIterator != partitionPoints.end(); pointIterator++)
|
||||
{
|
||||
if(currentPoint != MIPS_INVALID_PC)
|
||||
{
|
||||
uint32 beginAddress = currentPoint;
|
||||
uint32 endAddress = *pointIterator - 4;
|
||||
//Sanity checks
|
||||
assert((beginAddress & 0x07) == 0x00);
|
||||
assert((endAddress & 0x07) == 0x04);
|
||||
CreateBlock(beginAddress, endAddress);
|
||||
}
|
||||
currentPoint = *pointIterator;
|
||||
}
|
||||
uint32 currentPoint = MIPS_INVALID_PC;
|
||||
for(PartitionPointSet::const_iterator pointIterator(partitionPoints.begin());
|
||||
pointIterator != partitionPoints.end(); pointIterator++)
|
||||
{
|
||||
if(currentPoint != MIPS_INVALID_PC)
|
||||
{
|
||||
uint32 beginAddress = currentPoint;
|
||||
uint32 endAddress = *pointIterator - 4;
|
||||
//Sanity checks
|
||||
assert((beginAddress & 0x07) == 0x00);
|
||||
assert((endAddress & 0x07) == 0x04);
|
||||
CreateBlock(beginAddress, endAddress);
|
||||
}
|
||||
currentPoint = *pointIterator;
|
||||
}
|
||||
|
||||
//Convenient cutting for debugging purposes
|
||||
//for(uint32 address = functionAddress; address <= endAddress; address += 8)
|
||||
//{
|
||||
// uint32 beginAddress = address;
|
||||
// uint32 endAddress = address + 4;
|
||||
// //Sanity checks
|
||||
// assert((beginAddress & 0x07) == 0x00);
|
||||
// assert((endAddress & 0x07) == 0x04);
|
||||
// CreateBlock(beginAddress, endAddress);
|
||||
//}
|
||||
//for(uint32 address = functionAddress; address <= endAddress; address += 8)
|
||||
//{
|
||||
// uint32 beginAddress = address;
|
||||
// uint32 endAddress = address + 4;
|
||||
// //Sanity checks
|
||||
// assert((beginAddress & 0x07) == 0x00);
|
||||
// assert((endAddress & 0x07) == 0x04);
|
||||
// CreateBlock(beginAddress, endAddress);
|
||||
//}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ using namespace PS2;
|
||||
#define STATE_SCRATCH ("iop_scratch")
|
||||
|
||||
CSubSystem::CSubSystem()
|
||||
: m_cpu(MEMORYMAP_ENDIAN_LSBF, 0, 0x1FFFFFFF)
|
||||
, m_executor(m_cpu)
|
||||
: m_cpu(MEMORYMAP_ENDIAN_LSBF)
|
||||
, m_executor(m_cpu, (IOP_RAM_SIZE * 4))
|
||||
, m_ram(new uint8[IOP_RAM_SIZE])
|
||||
, m_scratchPad(new uint8[IOP_SCRATCH_SIZE])
|
||||
, m_spuRam(new uint8[SPU_RAM_SIZE])
|
||||
@ -211,7 +211,8 @@ unsigned int CSubSystem::ExecuteCpu(bool singleStep)
|
||||
}
|
||||
else
|
||||
{
|
||||
BasicBlockPtr nextBlock = m_executor.FindBlockAt(m_cpu.m_State.nPC);
|
||||
uint32 physicalPc = m_cpu.m_pAddrTranslator(&m_cpu, 0, m_cpu.m_State.nPC);
|
||||
BasicBlockPtr nextBlock = m_executor.FindBlockAt(physicalPc);
|
||||
if(nextBlock && nextBlock->GetSelfLoopCount() > 5000)
|
||||
{
|
||||
//Go a little bit faster if we're "stuck"
|
||||
|
@ -9,10 +9,10 @@ CPsfSubSystem::CPsfSubSystem(uint32 ramSize)
|
||||
: m_ram(new uint8[ramSize])
|
||||
, m_ramSize(ramSize)
|
||||
, m_spuRam(new uint8[SPURAMSIZE])
|
||||
, m_cpu(MEMORYMAP_ENDIAN_LSBF, 0, ramSize)
|
||||
, m_cpu(MEMORYMAP_ENDIAN_LSBF)
|
||||
, m_copScu(MIPS_REGSIZE_32)
|
||||
, m_copFpu(MIPS_REGSIZE_32)
|
||||
, m_executor(m_cpu)
|
||||
, m_executor(m_cpu, ramSize)
|
||||
, m_spuCore0(m_spuRam, SPURAMSIZE)
|
||||
, m_spuCore1(m_spuRam, SPURAMSIZE)
|
||||
, m_bios(m_cpu, m_ram, ramSize)
|
||||
|
@ -87,7 +87,7 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_PSX;_NULL_SIFMAN;FUNCTIONSVIEW_STANDALONE;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_NULL_SIFMAN;FUNCTIONSVIEW_STANDALONE;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(FrameworkRoot)\include;$(ProjectDir)\..\Source;$(ProjectDir)\..\..\..\Source;D:\Projects\CodeGen\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<ForcedIncludeFiles>StdAfx.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
@ -105,7 +105,7 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_PSX;_NULL_SIFMAN;FUNCTIONSVIEW_STANDALONE;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_NULL_SIFMAN;FUNCTIONSVIEW_STANDALONE;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(FrameworkRoot)\include;$(ProjectDir)\..\Source;$(ProjectDir)\..\..\..\Source;D:\Projects\CodeGen\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<ForcedIncludeFiles>StdAfx.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
@ -125,7 +125,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_PSX;_NULL_SIFMAN;_CRT_SECURE_NO_WARNINGS;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_NULL_SIFMAN;_CRT_SECURE_NO_WARNINGS;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(FrameworkRoot)\include;$(ProjectDir)\..\Source;$(ProjectDir)\..\..\..\Source;D:\Projects\CodeGen\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<ForcedIncludeFiles>StdAfx.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
@ -147,7 +147,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_PSX;_NULL_SIFMAN;_CRT_SECURE_NO_WARNINGS;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_NULL_SIFMAN;_CRT_SECURE_NO_WARNINGS;RAR_SUPPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(FrameworkRoot)\include;$(ProjectDir)\..\Source;$(ProjectDir)\..\..\..\Source;D:\Projects\CodeGen\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<ForcedIncludeFiles>StdAfx.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
|
Loading…
Reference in New Issue
Block a user