MipsExecutor is now owned by MIPS CPU context.

Will help to make new breakpoint implementation simpler.
This commit is contained in:
Jean-Philip Desjardins 2018-07-20 12:51:04 -04:00
parent f2f0b9e6ca
commit 050bf0f854
23 changed files with 536 additions and 523 deletions

View file

@ -0,0 +1,60 @@
#pragma once
#include "Types.h"
#include "BasicBlock.h"
class BlockLookupOneWay
{
public:
typedef CBasicBlock* BlockType;
BlockLookupOneWay(BlockType emptyBlock, uint32 maxAddress)
: m_emptyBlock(emptyBlock)
{
m_tableSize = maxAddress / INSTRUCTION_SIZE;
m_blockTable = new BlockType[m_tableSize];
}
~BlockLookupOneWay()
{
delete[] m_blockTable;
}
void Clear()
{
for(unsigned int i = 0; i < m_tableSize; i++)
{
m_blockTable[i] = m_emptyBlock;
}
}
void AddBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
assert(m_blockTable[address / INSTRUCTION_SIZE] == m_emptyBlock);
m_blockTable[address / INSTRUCTION_SIZE] = block;
}
void DeleteBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
assert(m_blockTable[address / INSTRUCTION_SIZE] != m_emptyBlock);
m_blockTable[address / INSTRUCTION_SIZE] = m_emptyBlock;
}
BlockType FindBlockAt(uint32 address) const
{
assert((address / INSTRUCTION_SIZE) < m_tableSize);
return m_blockTable[address / INSTRUCTION_SIZE];
}
private:
enum
{
INSTRUCTION_SIZE = 4,
};
BlockType m_emptyBlock = nullptr;
BlockType* m_blockTable = nullptr;
uint32 m_tableSize = 0;
};

102
Source/BlockLookupTwoWay.h Normal file
View file

@ -0,0 +1,102 @@
#pragma once
#include <cstring>
#include "Types.h"
#include "BasicBlock.h"
class BlockLookupTwoWay
{
public:
typedef CBasicBlock* BlockType;
BlockLookupTwoWay(BlockType emptyBlock, uint32 maxAddress)
: m_emptyBlock(emptyBlock)
{
m_subTableCount = (maxAddress + SUBTABLE_MASK) / SUBTABLE_SIZE;
assert(m_subTableCount != 0);
m_blockTable = new BlockType*[m_subTableCount];
memset(m_blockTable, 0, sizeof(BlockType*) * m_subTableCount);
}
~BlockLookupTwoWay()
{
for(unsigned int i = 0; i < m_subTableCount; i++)
{
auto subTable = m_blockTable[i];
if(subTable)
{
delete[] subTable;
}
}
delete[] m_blockTable;
}
void Clear()
{
for(unsigned int i = 0; i < m_subTableCount; i++)
{
auto subTable = m_blockTable[i];
if(subTable)
{
delete[] subTable;
m_blockTable[i] = nullptr;
}
}
}
void AddBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
uint32 hiAddress = address >> SUBTABLE_BITS;
uint32 loAddress = address & SUBTABLE_MASK;
assert(hiAddress < m_subTableCount);
auto& subTable = m_blockTable[hiAddress];
if(!subTable)
{
const uint32 subTableSize = SUBTABLE_SIZE / INSTRUCTION_SIZE;
subTable = new BlockType[subTableSize];
for(uint32 i = 0; i < subTableSize; i++)
{
subTable[i] = m_emptyBlock;
}
}
assert(subTable[loAddress / INSTRUCTION_SIZE] == m_emptyBlock);
subTable[loAddress / INSTRUCTION_SIZE] = block;
}
void DeleteBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
uint32 hiAddress = address >> SUBTABLE_BITS;
uint32 loAddress = address & SUBTABLE_MASK;
assert(hiAddress < m_subTableCount);
auto& subTable = m_blockTable[hiAddress];
assert(subTable);
assert(subTable[loAddress / INSTRUCTION_SIZE] != m_emptyBlock);
subTable[loAddress / INSTRUCTION_SIZE] = m_emptyBlock;
}
BlockType FindBlockAt(uint32 address) const
{
uint32 hiAddress = address >> SUBTABLE_BITS;
uint32 loAddress = address & SUBTABLE_MASK;
assert(hiAddress < m_subTableCount);
auto& subTable = m_blockTable[hiAddress];
if(!subTable) return m_emptyBlock;
auto result = subTable[loAddress / INSTRUCTION_SIZE];
return result;
}
private:
enum
{
SUBTABLE_BITS = 16,
SUBTABLE_SIZE = (1 << SUBTABLE_BITS),
SUBTABLE_MASK = (SUBTABLE_SIZE - 1),
INSTRUCTION_SIZE = 4,
};
BlockType m_emptyBlock = nullptr;
BlockType** m_blockTable = nullptr;
uint32 m_subTableCount = 0;
};

View file

@ -118,6 +118,8 @@ set(COMMON_SRC_FILES
AppConfig.h AppConfig.h
BasicBlock.cpp BasicBlock.cpp
BasicBlock.h BasicBlock.h
BlockLookupOneWay.h
BlockLookupTwoWay.h
ControllerInfo.cpp ControllerInfo.cpp
ControllerInfo.h ControllerInfo.h
COP_FPU.cpp COP_FPU.cpp
@ -201,6 +203,7 @@ set(COMMON_SRC_FILES
ElfFile.h ElfFile.h
FrameDump.cpp FrameDump.cpp
FrameDump.h FrameDump.h
GenericMipsExecutor.h
gs/GsCachedArea.cpp gs/GsCachedArea.cpp
gs/GsCachedArea.h gs/GsCachedArea.h
gs/GSH_Null.cpp gs/GSH_Null.cpp
@ -299,7 +302,6 @@ set(COMMON_SRC_FILES
iop/Iop_Vblank.h iop/Iop_Vblank.h
iop/IopBios.cpp iop/IopBios.cpp
iop/IopBios.h iop/IopBios.h
iop/IopExecutor.h
iop/OpticalMediaDevice.cpp iop/OpticalMediaDevice.cpp
iop/OpticalMediaDevice.h iop/OpticalMediaDevice.h
ISO9660/DirectoryRecord.cpp ISO9660/DirectoryRecord.cpp

View file

@ -0,0 +1,308 @@
#pragma once
#include <list>
#include "MIPS.h"
#include "BasicBlock.h"
#include "BlockLookupOneWay.h"
#include "BlockLookupTwoWay.h"
static bool IsInsideRange(uint32 address, uint32 start, uint32 end)
{
return (address >= start) && (address <= end);
}
typedef uint32 (*TranslateFunctionType)(CMIPS*, uint32);
typedef std::shared_ptr<CBasicBlock> BasicBlockPtr;
template <typename BlockLookupType>
class CGenericMipsExecutor : public CMipsExecutor
{
public:
enum
{
MAX_BLOCK_SIZE = 0x1000,
};
CGenericMipsExecutor(CMIPS& context, uint32 maxAddress)
: m_emptyBlock(std::make_shared<CBasicBlock>(context, MIPS_INVALID_PC, MIPS_INVALID_PC))
, m_context(context)
, m_maxAddress(maxAddress)
, m_addressMask(maxAddress - 1)
, m_blockLookup(m_emptyBlock.get(), maxAddress)
{
m_emptyBlock->Compile();
assert(!context.m_emptyBlockHandler);
context.m_emptyBlockHandler =
[&](CMIPS* context) {
uint32 address = m_context.m_State.nPC & m_addressMask;
PartitionFunction(address);
auto block = FindBlockStartingAt(address);
assert(!block->IsEmpty());
block->Execute();
};
}
virtual ~CGenericMipsExecutor() = default;
int Execute(int cycles) override
{
m_context.m_State.cycleQuota = cycles;
while(m_context.m_State.nHasException == 0)
{
uint32 address = m_context.m_State.nPC & m_addressMask;
auto block = m_blockLookup.FindBlockAt(address);
#ifdef DEBUGGER_INCLUDED
if(!m_breakpointsDisabledOnce && MustBreak()) break;
m_breakpointsDisabledOnce = false;
#endif
block->Execute();
}
m_context.m_State.nHasException &= ~MIPS_EXECUTION_STATUS_QUOTADONE;
return m_context.m_State.cycleQuota;
}
CBasicBlock* FindBlockStartingAt(uint32 address) const
{
return m_blockLookup.FindBlockAt(address);
}
void Reset() override
{
m_blockLookup.Clear();
m_blocks.clear();
m_blockLinks.clear();
m_pendingBlockLinks.clear();
}
void ClearActiveBlocksInRange(uint32 start, uint32 end) override
{
ClearActiveBlocksInRangeInternal(start, end, nullptr);
}
#ifdef DEBUGGER_INCLUDED
bool MustBreak() const override
{
uint32 currentPc = m_context.m_State.nPC & m_addressMask;
auto block = m_blockLookup.FindBlockAt(currentPc);
for(auto breakPointAddress : m_context.m_breakpoints)
{
if(currentPc == breakPointAddress) return true;
if(block != NULL)
{
if(breakPointAddress >= block->GetBeginAddress() && breakPointAddress <= block->GetEndAddress()) return true;
}
}
return false;
}
void DisableBreakpointsOnce() override
{
m_breakpointsDisabledOnce = true;
}
#endif
protected:
//Outgoing block link
struct BLOCK_LINK
{
CBasicBlock::LINK_SLOT slot;
uint32 address;
};
typedef std::list<BasicBlockPtr> BlockList;
typedef std::multimap<uint32, BLOCK_LINK> BlockLinkMap;
bool HasBlockAt(uint32 address) const
{
auto block = m_blockLookup.FindBlockAt(address);
return !block->IsEmpty();
}
void CreateBlock(uint32 start, uint32 end)
{
assert(!HasBlockAt(start));
auto block = BlockFactory(m_context, start, end);
m_blockLookup.AddBlock(block.get());
m_blocks.push_back(std::move(block));
}
virtual BasicBlockPtr BlockFactory(CMIPS& context, uint32 start, uint32 end)
{
auto result = std::make_shared<CBasicBlock>(context, start, end);
result->Compile();
return result;
}
void SetupBlockLinks(uint32 startAddress, uint32 endAddress, uint32 branchAddress)
{
auto block = m_blockLookup.FindBlockAt(startAddress);
{
uint32 nextBlockAddress = (endAddress + 4) & m_addressMask;
block->SetLinkTargetAddress(CBasicBlock::LINK_SLOT_NEXT, nextBlockAddress);
auto link = std::make_pair(nextBlockAddress, BLOCK_LINK{CBasicBlock::LINK_SLOT_NEXT, startAddress});
auto nextBlock = m_blockLookup.FindBlockAt(nextBlockAddress);
if(!nextBlock->IsEmpty())
{
block->LinkBlock(CBasicBlock::LINK_SLOT_NEXT, nextBlock);
m_blockLinks.insert(link);
}
else
{
m_pendingBlockLinks.insert(link);
}
}
if(branchAddress != 0)
{
branchAddress &= m_addressMask;
block->SetLinkTargetAddress(CBasicBlock::LINK_SLOT_BRANCH, branchAddress);
auto link = std::make_pair(branchAddress, BLOCK_LINK{CBasicBlock::LINK_SLOT_BRANCH, startAddress});
auto branchBlock = m_blockLookup.FindBlockAt(branchAddress);
if(!branchBlock->IsEmpty())
{
block->LinkBlock(CBasicBlock::LINK_SLOT_BRANCH, branchBlock);
m_blockLinks.insert(link);
}
else
{
m_pendingBlockLinks.insert(link);
}
}
//Resolve any block links that could be valid now that block has been created
{
auto lowerBound = m_pendingBlockLinks.lower_bound(startAddress);
auto upperBound = m_pendingBlockLinks.upper_bound(startAddress);
for(auto blockLinkIterator = lowerBound; blockLinkIterator != upperBound; blockLinkIterator++)
{
const auto& blockLink = blockLinkIterator->second;
auto referringBlock = m_blockLookup.FindBlockAt(blockLink.address);
if(referringBlock->IsEmpty()) continue;
referringBlock->LinkBlock(blockLink.slot, block);
m_blockLinks.insert(*blockLinkIterator);
}
m_pendingBlockLinks.erase(lowerBound, upperBound);
}
}
virtual void PartitionFunction(uint32 startAddress)
{
uint32 endAddress = startAddress + MAX_BLOCK_SIZE;
uint32 branchAddress = 0;
for(uint32 address = startAddress; address < endAddress; address += 4)
{
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
auto branchType = m_context.m_pArch->IsInstructionBranch(&m_context, address, opcode);
if(branchType == MIPS_BRANCH_NORMAL)
{
branchAddress = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, address, opcode);
endAddress = address + 4;
break;
}
else if(branchType == MIPS_BRANCH_NODELAY)
{
endAddress = address;
break;
}
}
assert((endAddress - startAddress) <= MAX_BLOCK_SIZE);
assert(endAddress <= m_maxAddress);
CreateBlock(startAddress, endAddress);
SetupBlockLinks(startAddress, endAddress, branchAddress);
}
//Unlink and removes block from all of our bookkeeping structures
void OrphanBlock(CBasicBlock* block)
{
auto orphanBlockLinkSlot =
[&](CBasicBlock::LINK_SLOT linkSlot) {
auto slotSearch =
[&](const std::pair<uint32, BLOCK_LINK>& link) {
return (link.second.address == block->GetBeginAddress()) &&
(link.second.slot == linkSlot);
};
uint32 linkTargetAddress = block->GetLinkTargetAddress(linkSlot);
//Check if block has this specific link slot
if(linkTargetAddress != MIPS_INVALID_PC)
{
//If it has that link slot, it's either linked or pending to be linked
auto slotIterator = std::find_if(m_blockLinks.begin(), m_blockLinks.end(), slotSearch);
if(slotIterator != std::end(m_blockLinks))
{
block->UnlinkBlock(linkSlot);
m_blockLinks.erase(slotIterator);
}
else
{
slotIterator = std::find_if(m_pendingBlockLinks.begin(), m_pendingBlockLinks.end(), slotSearch);
assert(slotIterator != std::end(m_pendingBlockLinks));
m_pendingBlockLinks.erase(slotIterator);
}
}
};
orphanBlockLinkSlot(CBasicBlock::LINK_SLOT_NEXT);
orphanBlockLinkSlot(CBasicBlock::LINK_SLOT_BRANCH);
}
void ClearActiveBlocksInRangeInternal(uint32 start, uint32 end, CBasicBlock* protectedBlock)
{
//Widen scan range since blocks starting before the range can end in the range
uint32 scanStart = static_cast<uint32>(std::max<int64>(0, static_cast<uint64>(start) - MAX_BLOCK_SIZE));
uint32 scanEnd = end;
assert(scanEnd > scanStart);
std::set<CBasicBlock*> clearedBlocks;
for(uint32 address = scanStart; address < scanEnd; address += 4)
{
auto block = m_blockLookup.FindBlockAt(address);
if(block->IsEmpty()) continue;
if(block == protectedBlock) continue;
if(!IsInsideRange(block->GetBeginAddress(), start, end) && !IsInsideRange(block->GetEndAddress(), start, end)) continue;
clearedBlocks.insert(block);
m_blockLookup.DeleteBlock(block);
}
//Remove pending block link entries for the blocks that are about to be cleared
for(auto& block : clearedBlocks)
{
OrphanBlock(block);
}
//Undo all stale links
for(auto& block : clearedBlocks)
{
auto lowerBound = m_blockLinks.lower_bound(block->GetBeginAddress());
auto upperBound = m_blockLinks.upper_bound(block->GetBeginAddress());
for(auto blockLinkIterator = lowerBound; blockLinkIterator != upperBound; blockLinkIterator++)
{
const auto& blockLink = blockLinkIterator->second;
auto referringBlock = m_blockLookup.FindBlockAt(blockLink.address);
if(referringBlock->IsEmpty()) continue;
referringBlock->UnlinkBlock(blockLink.slot);
m_pendingBlockLinks.insert(*blockLinkIterator);
}
m_blockLinks.erase(lowerBound, upperBound);
}
if(!clearedBlocks.empty())
{
m_blocks.remove_if([&](const BasicBlockPtr& block) { return clearedBlocks.find(block.get()) != std::end(clearedBlocks); });
}
}
BlockList m_blocks;
BasicBlockPtr m_emptyBlock;
BlockLinkMap m_blockLinks;
BlockLinkMap m_pendingBlockLinks;
CMIPS& m_context;
uint32 m_maxAddress = 0;
uint32 m_addressMask = 0;
BlockLookupType m_blockLookup;
#ifdef DEBUGGER_INCLUDED
bool m_breakpointsDisabledOnce = false;
#endif
};

View file

@ -3,6 +3,7 @@
#include "Types.h" #include "Types.h"
#include "MemoryMap.h" #include "MemoryMap.h"
#include "MipsExecutor.h"
#include "MIPSArchitecture.h" #include "MIPSArchitecture.h"
#include "MIPSCoprocessor.h" #include "MIPSCoprocessor.h"
#include "MIPSAnalysis.h" #include "MIPSAnalysis.h"
@ -145,6 +146,7 @@ public:
CMIPSArchitecture* m_pArch = nullptr; CMIPSArchitecture* m_pArch = nullptr;
CMIPSCoprocessor* m_pCOP[4]; CMIPSCoprocessor* m_pCOP[4];
CMemoryMap* m_pMemoryMap = nullptr; CMemoryMap* m_pMemoryMap = nullptr;
std::unique_ptr<CMipsExecutor> m_executor;
BreakpointSet m_breakpoints; BreakpointSet m_breakpoints;
CMIPSAnalysis* m_analysis = nullptr; CMIPSAnalysis* m_analysis = nullptr;

View file

@ -1,458 +1,17 @@
#pragma once #pragma once
#include <list> #include "Types.h"
#include "MIPS.h"
#include "BasicBlock.h"
static bool IsInsideRange(uint32 address, uint32 start, uint32 end)
{
return (address >= start) && (address <= end);
}
class BlockLookupOneWay
{
public:
typedef CBasicBlock* BlockType;
BlockLookupOneWay(BlockType emptyBlock, uint32 maxAddress)
: m_emptyBlock(emptyBlock)
{
m_tableSize = maxAddress / INSTRUCTION_SIZE;
m_blockTable = new BlockType[m_tableSize];
}
~BlockLookupOneWay()
{
delete[] m_blockTable;
}
void Clear()
{
for(unsigned int i = 0; i < m_tableSize; i++)
{
m_blockTable[i] = m_emptyBlock;
}
}
void AddBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
assert(m_blockTable[address / INSTRUCTION_SIZE] == m_emptyBlock);
m_blockTable[address / INSTRUCTION_SIZE] = block;
}
void DeleteBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
assert(m_blockTable[address / INSTRUCTION_SIZE] != m_emptyBlock);
m_blockTable[address / INSTRUCTION_SIZE] = m_emptyBlock;
}
BlockType FindBlockAt(uint32 address) const
{
assert((address / INSTRUCTION_SIZE) < m_tableSize);
return m_blockTable[address / INSTRUCTION_SIZE];
}
private:
enum
{
INSTRUCTION_SIZE = 4,
};
BlockType m_emptyBlock = nullptr;
BlockType* m_blockTable = nullptr;
uint32 m_tableSize = 0;
};
class BlockLookupTwoWay
{
public:
typedef CBasicBlock* BlockType;
BlockLookupTwoWay(BlockType emptyBlock, uint32 maxAddress)
: m_emptyBlock(emptyBlock)
{
m_subTableCount = (maxAddress + SUBTABLE_MASK) / SUBTABLE_SIZE;
assert(m_subTableCount != 0);
m_blockTable = new BlockType*[m_subTableCount];
memset(m_blockTable, 0, sizeof(BlockType*) * m_subTableCount);
}
~BlockLookupTwoWay()
{
for(unsigned int i = 0; i < m_subTableCount; i++)
{
auto subTable = m_blockTable[i];
if(subTable)
{
delete[] subTable;
}
}
delete[] m_blockTable;
}
void Clear()
{
for(unsigned int i = 0; i < m_subTableCount; i++)
{
auto subTable = m_blockTable[i];
if(subTable)
{
delete[] subTable;
m_blockTable[i] = nullptr;
}
}
}
void AddBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
uint32 hiAddress = address >> SUBTABLE_BITS;
uint32 loAddress = address & SUBTABLE_MASK;
assert(hiAddress < m_subTableCount);
auto& subTable = m_blockTable[hiAddress];
if(!subTable)
{
const uint32 subTableSize = SUBTABLE_SIZE / INSTRUCTION_SIZE;
subTable = new BlockType[subTableSize];
for(uint32 i = 0; i < subTableSize; i++)
{
subTable[i] = m_emptyBlock;
}
}
assert(subTable[loAddress / INSTRUCTION_SIZE] == m_emptyBlock);
subTable[loAddress / INSTRUCTION_SIZE] = block;
}
void DeleteBlock(BlockType block)
{
uint32 address = block->GetBeginAddress();
uint32 hiAddress = address >> SUBTABLE_BITS;
uint32 loAddress = address & SUBTABLE_MASK;
assert(hiAddress < m_subTableCount);
auto& subTable = m_blockTable[hiAddress];
assert(subTable);
assert(subTable[loAddress / INSTRUCTION_SIZE] != m_emptyBlock);
subTable[loAddress / INSTRUCTION_SIZE] = m_emptyBlock;
}
BlockType FindBlockAt(uint32 address) const
{
uint32 hiAddress = address >> SUBTABLE_BITS;
uint32 loAddress = address & SUBTABLE_MASK;
assert(hiAddress < m_subTableCount);
auto& subTable = m_blockTable[hiAddress];
if(!subTable) return m_emptyBlock;
auto result = subTable[loAddress / INSTRUCTION_SIZE];
return result;
}
private:
enum
{
SUBTABLE_BITS = 16,
SUBTABLE_SIZE = (1 << SUBTABLE_BITS),
SUBTABLE_MASK = (SUBTABLE_SIZE - 1),
INSTRUCTION_SIZE = 4,
};
BlockType m_emptyBlock = nullptr;
BlockType** m_blockTable = nullptr;
uint32 m_subTableCount = 0;
};
typedef uint32 (*TranslateFunctionType)(CMIPS*, uint32);
typedef std::shared_ptr<CBasicBlock> BasicBlockPtr;
template <typename BlockLookupType>
class CMipsExecutor class CMipsExecutor
{ {
public: public:
enum
{
MAX_BLOCK_SIZE = 0x1000,
};
CMipsExecutor(CMIPS& context, uint32 maxAddress)
: m_emptyBlock(std::make_shared<CBasicBlock>(context, MIPS_INVALID_PC, MIPS_INVALID_PC))
, m_context(context)
, m_maxAddress(maxAddress)
, m_addressMask(maxAddress - 1)
, m_blockLookup(m_emptyBlock.get(), maxAddress)
{
m_emptyBlock->Compile();
assert(!context.m_emptyBlockHandler);
context.m_emptyBlockHandler =
[&](CMIPS* context) {
uint32 address = m_context.m_State.nPC & m_addressMask;
PartitionFunction(address);
auto block = FindBlockStartingAt(address);
assert(!block->IsEmpty());
block->Execute();
};
}
virtual ~CMipsExecutor() = default; virtual ~CMipsExecutor() = default;
virtual void Reset() = 0;
int Execute(int cycles) virtual int Execute(int) = 0;
{ virtual void ClearActiveBlocksInRange(uint32 start, uint32 end) = 0;
m_context.m_State.cycleQuota = cycles;
while(m_context.m_State.nHasException == 0)
{
uint32 address = m_context.m_State.nPC & m_addressMask;
auto block = m_blockLookup.FindBlockAt(address);
#ifdef DEBUGGER_INCLUDED
if(!m_breakpointsDisabledOnce && MustBreak()) break;
m_breakpointsDisabledOnce = false;
#endif
block->Execute();
}
m_context.m_State.nHasException &= ~MIPS_EXECUTION_STATUS_QUOTADONE;
return m_context.m_State.cycleQuota;
}
CBasicBlock* FindBlockStartingAt(uint32 address) const
{
return m_blockLookup.FindBlockAt(address);
}
virtual void Reset()
{
m_blockLookup.Clear();
m_blocks.clear();
m_blockLinks.clear();
m_pendingBlockLinks.clear();
}
virtual void ClearActiveBlocksInRange(uint32 start, uint32 end)
{
ClearActiveBlocksInRangeInternal(start, end, nullptr);
}
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
bool MustBreak() const virtual bool MustBreak() const = 0;
{ virtual void DisableBreakpointsOnce() = 0;
uint32 currentPc = m_context.m_State.nPC & m_addressMask;
auto block = m_blockLookup.FindBlockAt(currentPc);
for(auto breakPointAddress : m_context.m_breakpoints)
{
if(currentPc == breakPointAddress) return true;
if(block != NULL)
{
if(breakPointAddress >= block->GetBeginAddress() && breakPointAddress <= block->GetEndAddress()) return true;
}
}
return false;
}
void DisableBreakpointsOnce()
{
m_breakpointsDisabledOnce = true;
}
#endif
protected:
//Outgoing block link
struct BLOCK_LINK
{
CBasicBlock::LINK_SLOT slot;
uint32 address;
};
typedef std::list<BasicBlockPtr> BlockList;
typedef std::multimap<uint32, BLOCK_LINK> BlockLinkMap;
bool HasBlockAt(uint32 address) const
{
auto block = m_blockLookup.FindBlockAt(address);
return !block->IsEmpty();
}
void CreateBlock(uint32 start, uint32 end)
{
assert(!HasBlockAt(start));
auto block = BlockFactory(m_context, start, end);
m_blockLookup.AddBlock(block.get());
m_blocks.push_back(std::move(block));
}
virtual BasicBlockPtr BlockFactory(CMIPS& context, uint32 start, uint32 end)
{
auto result = std::make_shared<CBasicBlock>(context, start, end);
result->Compile();
return result;
}
void SetupBlockLinks(uint32 startAddress, uint32 endAddress, uint32 branchAddress)
{
auto block = m_blockLookup.FindBlockAt(startAddress);
{
uint32 nextBlockAddress = (endAddress + 4) & m_addressMask;
block->SetLinkTargetAddress(CBasicBlock::LINK_SLOT_NEXT, nextBlockAddress);
auto link = std::make_pair(nextBlockAddress, BLOCK_LINK{CBasicBlock::LINK_SLOT_NEXT, startAddress});
auto nextBlock = m_blockLookup.FindBlockAt(nextBlockAddress);
if(!nextBlock->IsEmpty())
{
block->LinkBlock(CBasicBlock::LINK_SLOT_NEXT, nextBlock);
m_blockLinks.insert(link);
}
else
{
m_pendingBlockLinks.insert(link);
}
}
if(branchAddress != 0)
{
branchAddress &= m_addressMask;
block->SetLinkTargetAddress(CBasicBlock::LINK_SLOT_BRANCH, branchAddress);
auto link = std::make_pair(branchAddress, BLOCK_LINK{CBasicBlock::LINK_SLOT_BRANCH, startAddress});
auto branchBlock = m_blockLookup.FindBlockAt(branchAddress);
if(!branchBlock->IsEmpty())
{
block->LinkBlock(CBasicBlock::LINK_SLOT_BRANCH, branchBlock);
m_blockLinks.insert(link);
}
else
{
m_pendingBlockLinks.insert(link);
}
}
//Resolve any block links that could be valid now that block has been created
{
auto lowerBound = m_pendingBlockLinks.lower_bound(startAddress);
auto upperBound = m_pendingBlockLinks.upper_bound(startAddress);
for(auto blockLinkIterator = lowerBound; blockLinkIterator != upperBound; blockLinkIterator++)
{
const auto& blockLink = blockLinkIterator->second;
auto referringBlock = m_blockLookup.FindBlockAt(blockLink.address);
if(referringBlock->IsEmpty()) continue;
referringBlock->LinkBlock(blockLink.slot, block);
m_blockLinks.insert(*blockLinkIterator);
}
m_pendingBlockLinks.erase(lowerBound, upperBound);
}
}
virtual void PartitionFunction(uint32 startAddress)
{
uint32 endAddress = startAddress + MAX_BLOCK_SIZE;
uint32 branchAddress = 0;
for(uint32 address = startAddress; address < endAddress; address += 4)
{
uint32 opcode = m_context.m_pMemoryMap->GetInstruction(address);
auto branchType = m_context.m_pArch->IsInstructionBranch(&m_context, address, opcode);
if(branchType == MIPS_BRANCH_NORMAL)
{
branchAddress = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, address, opcode);
endAddress = address + 4;
break;
}
else if(branchType == MIPS_BRANCH_NODELAY)
{
endAddress = address;
break;
}
}
assert((endAddress - startAddress) <= MAX_BLOCK_SIZE);
assert(endAddress <= m_maxAddress);
CreateBlock(startAddress, endAddress);
SetupBlockLinks(startAddress, endAddress, branchAddress);
}
//Unlink and removes block from all of our bookkeeping structures
void OrphanBlock(CBasicBlock* block)
{
auto orphanBlockLinkSlot =
[&](CBasicBlock::LINK_SLOT linkSlot) {
auto slotSearch =
[&](const std::pair<uint32, BLOCK_LINK>& link) {
return (link.second.address == block->GetBeginAddress()) &&
(link.second.slot == linkSlot);
};
uint32 linkTargetAddress = block->GetLinkTargetAddress(linkSlot);
//Check if block has this specific link slot
if(linkTargetAddress != MIPS_INVALID_PC)
{
//If it has that link slot, it's either linked or pending to be linked
auto slotIterator = std::find_if(m_blockLinks.begin(), m_blockLinks.end(), slotSearch);
if(slotIterator != std::end(m_blockLinks))
{
block->UnlinkBlock(linkSlot);
m_blockLinks.erase(slotIterator);
}
else
{
slotIterator = std::find_if(m_pendingBlockLinks.begin(), m_pendingBlockLinks.end(), slotSearch);
assert(slotIterator != std::end(m_pendingBlockLinks));
m_pendingBlockLinks.erase(slotIterator);
}
}
};
orphanBlockLinkSlot(CBasicBlock::LINK_SLOT_NEXT);
orphanBlockLinkSlot(CBasicBlock::LINK_SLOT_BRANCH);
}
void ClearActiveBlocksInRangeInternal(uint32 start, uint32 end, CBasicBlock* protectedBlock)
{
//Widen scan range since blocks starting before the range can end in the range
uint32 scanStart = static_cast<uint32>(std::max<int64>(0, static_cast<uint64>(start) - MAX_BLOCK_SIZE));
uint32 scanEnd = end;
assert(scanEnd > scanStart);
std::set<CBasicBlock*> clearedBlocks;
for(uint32 address = scanStart; address < scanEnd; address += 4)
{
auto block = m_blockLookup.FindBlockAt(address);
if(block->IsEmpty()) continue;
if(block == protectedBlock) continue;
if(!IsInsideRange(block->GetBeginAddress(), start, end) && !IsInsideRange(block->GetEndAddress(), start, end)) continue;
clearedBlocks.insert(block);
m_blockLookup.DeleteBlock(block);
}
//Remove pending block link entries for the blocks that are about to be cleared
for(auto& block : clearedBlocks)
{
OrphanBlock(block);
}
//Undo all stale links
for(auto& block : clearedBlocks)
{
auto lowerBound = m_blockLinks.lower_bound(block->GetBeginAddress());
auto upperBound = m_blockLinks.upper_bound(block->GetBeginAddress());
for(auto blockLinkIterator = lowerBound; blockLinkIterator != upperBound; blockLinkIterator++)
{
const auto& blockLink = blockLinkIterator->second;
auto referringBlock = m_blockLookup.FindBlockAt(blockLink.address);
if(referringBlock->IsEmpty()) continue;
referringBlock->UnlinkBlock(blockLink.slot);
m_pendingBlockLinks.insert(*blockLinkIterator);
}
m_blockLinks.erase(lowerBound, upperBound);
}
if(!clearedBlocks.empty())
{
m_blocks.remove_if([&](const BasicBlockPtr& block) { return clearedBlocks.find(block.get()) != std::end(clearedBlocks); });
}
}
BlockList m_blocks;
BasicBlockPtr m_emptyBlock;
BlockLinkMap m_blockLinks;
BlockLinkMap m_pendingBlockLinks;
CMIPS& m_context;
uint32 m_maxAddress = 0;
uint32 m_addressMask = 0;
BlockLookupType m_blockLookup;
#ifdef DEBUGGER_INCLUDED
bool m_breakpointsDisabledOnce = false;
#endif #endif
}; };

View file

@ -8,6 +8,7 @@
#include "PS2VM.h" #include "PS2VM.h"
#include "PS2VM_Preferences.h" #include "PS2VM_Preferences.h"
#include "ee/PS2OS.h" #include "ee/PS2OS.h"
#include "ee/EeExecutor.h"
#include "Ps2Const.h" #include "Ps2Const.h"
#include "iop/Iop_SifManPs2.h" #include "iop/Iop_SifManPs2.h"
#include "StdStream.h" #include "StdStream.h"
@ -470,9 +471,9 @@ void CPS2VM::PauseImpl()
void CPS2VM::ResumeImpl() void CPS2VM::ResumeImpl()
{ {
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
m_ee->m_executor.DisableBreakpointsOnce(); m_ee->m_EE.m_executor->DisableBreakpointsOnce();
m_iop->m_executor.DisableBreakpointsOnce(); m_iop->m_cpu.m_executor->DisableBreakpointsOnce();
m_ee->m_vpu1->DisableBreakpointsOnce(); m_ee->m_VU1.m_executor->DisableBreakpointsOnce();
#endif #endif
m_nStatus = RUNNING; m_nStatus = RUNNING;
} }
@ -577,7 +578,7 @@ void CPS2VM::UpdateEe()
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
if(m_singleStepEe) break; if(m_singleStepEe) break;
if(m_ee->m_executor.MustBreak()) break; if(m_ee->m_EE.m_executor->MustBreak()) break;
#endif #endif
} }
} }
@ -608,7 +609,7 @@ void CPS2VM::UpdateIop()
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
if(m_singleStepIop) break; if(m_singleStepIop) break;
if(m_iop->m_executor.MustBreak()) break; if(m_iop->m_cpu.m_executor->MustBreak()) break;
#endif #endif
} }
} }
@ -715,7 +716,7 @@ void CPS2VM::EmuThread()
#ifdef PROFILE #ifdef PROFILE
CProfilerZone profilerZone(m_otherProfilerZone); CProfilerZone profilerZone(m_otherProfilerZone);
#endif #endif
m_ee->m_executor.AddExceptionHandler(); static_cast<CEeExecutor*>(m_ee->m_EE.m_executor.get())->AddExceptionHandler();
while(1) while(1)
{ {
while(m_mailBox.IsPending()) while(m_mailBox.IsPending())
@ -792,9 +793,9 @@ void CPS2VM::EmuThread()
} }
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
if( if(
m_ee->m_executor.MustBreak() || m_ee->m_EE.m_executor->MustBreak() ||
m_iop->m_executor.MustBreak() || m_iop->m_cpu.m_executor->MustBreak() ||
m_ee->m_vpu1->MustBreak() || m_ee->m_VU1.m_executor->MustBreak() ||
m_singleStepEe || m_singleStepIop || m_singleStepVu0 || m_singleStepVu1) m_singleStepEe || m_singleStepIop || m_singleStepVu0 || m_singleStepVu1)
{ {
m_nStatus = PAUSED; m_nStatus = PAUSED;
@ -808,5 +809,5 @@ void CPS2VM::EmuThread()
#endif #endif
} }
} }
m_ee->m_executor.RemoveExceptionHandler(); static_cast<CEeExecutor*>(m_ee->m_EE.m_executor.get())->RemoveExceptionHandler();
} }

View file

@ -33,7 +33,7 @@
static CEeExecutor* g_eeExecutor = nullptr; static CEeExecutor* g_eeExecutor = nullptr;
CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram) CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram)
: CMipsExecutor(context, 0x20000000) : CGenericMipsExecutor(context, 0x20000000)
, m_ram(ram) , m_ram(ram)
{ {
m_pageSize = framework_getpagesize(); m_pageSize = framework_getpagesize();
@ -96,7 +96,7 @@ void CEeExecutor::RemoveExceptionHandler()
void CEeExecutor::Reset() void CEeExecutor::Reset()
{ {
SetMemoryProtected(m_ram, PS2::EE_RAM_SIZE, false); SetMemoryProtected(m_ram, PS2::EE_RAM_SIZE, false);
CMipsExecutor::Reset(); CGenericMipsExecutor::Reset();
} }
void CEeExecutor::ClearActiveBlocksInRange(uint32 start, uint32 end) void CEeExecutor::ClearActiveBlocksInRange(uint32 start, uint32 end)
@ -117,7 +117,7 @@ BasicBlockPtr CEeExecutor::BlockFactory(CMIPS& context, uint32 start, uint32 end
{ {
SetMemoryProtected(m_ram + start, end - start + 4, true); SetMemoryProtected(m_ram + start, end - start + 4, true);
} }
return CMipsExecutor::BlockFactory(context, start, end); return CGenericMipsExecutor::BlockFactory(context, start, end);
} }
bool CEeExecutor::HandleAccessFault(intptr_t ptr) bool CEeExecutor::HandleAccessFault(intptr_t ptr)

View file

@ -9,9 +9,9 @@
#include <signal.h> #include <signal.h>
#endif #endif
#include "../MipsExecutor.h" #include "../GenericMipsExecutor.h"
class CEeExecutor : public CMipsExecutor<BlockLookupTwoWay> class CEeExecutor : public CGenericMipsExecutor<BlockLookupTwoWay>
{ {
public: public:
CEeExecutor(CMIPS&, uint8*); CEeExecutor(CMIPS&, uint8*);

View file

@ -1,4 +1,6 @@
#include "Ee_SubSystem.h" #include "Ee_SubSystem.h"
#include "EeExecutor.h"
#include "VuExecutor.h"
#include "../Ps2Const.h" #include "../Ps2Const.h"
#include "../Log.h" #include "../Log.h"
#include "../MemoryStateFile.h" #include "../MemoryStateFile.h"
@ -34,7 +36,6 @@ CSubSystem::CSubSystem(uint8* iopRam, CIopBios& iopBios)
, m_EE(MEMORYMAP_ENDIAN_LSBF) , m_EE(MEMORYMAP_ENDIAN_LSBF)
, m_VU0(MEMORYMAP_ENDIAN_LSBF) , m_VU0(MEMORYMAP_ENDIAN_LSBF)
, m_VU1(MEMORYMAP_ENDIAN_LSBF) , m_VU1(MEMORYMAP_ENDIAN_LSBF)
, m_executor(m_EE, m_ram)
, m_dmac(m_ram, m_spr, m_vuMem0, m_EE) , m_dmac(m_ram, m_spr, m_vuMem0, m_EE)
, m_gif(m_gs, m_ram, m_spr) , m_gif(m_gs, m_ram, m_spr)
, m_sif(m_dmac, m_ram, iopRam) , m_sif(m_dmac, m_ram, iopRam)
@ -60,6 +61,8 @@ CSubSystem::CSubSystem(uint8* iopRam, CIopBios& iopBios)
//EmotionEngine context setup //EmotionEngine context setup
{ {
m_EE.m_executor = std::make_unique<CEeExecutor>(m_EE, m_ram);
//Read map //Read map
m_EE.m_pMemoryMap->InsertReadMap(0x00000000, 0x01FFFFFF, m_ram, 0x00); m_EE.m_pMemoryMap->InsertReadMap(0x00000000, 0x01FFFFFF, m_ram, 0x00);
m_EE.m_pMemoryMap->InsertReadMap(PS2::EE_SPR_ADDR, PS2::EE_SPR_ADDR + PS2::EE_SPR_SIZE - 1, m_spr, 0x01); m_EE.m_pMemoryMap->InsertReadMap(PS2::EE_SPR_ADDR, PS2::EE_SPR_ADDR + PS2::EE_SPR_SIZE - 1, m_spr, 0x01);
@ -96,6 +99,8 @@ CSubSystem::CSubSystem(uint8* iopRam, CIopBios& iopBios)
//Vector Unit 0 context setup //Vector Unit 0 context setup
{ {
m_VU0.m_executor = std::make_unique<CVuExecutor>(m_VU0, PS2::MICROMEM0SIZE);
m_VU0.m_pMemoryMap->InsertReadMap(0x00000000, 0x00000FFF, m_vuMem0, 0x01); m_VU0.m_pMemoryMap->InsertReadMap(0x00000000, 0x00000FFF, m_vuMem0, 0x01);
m_VU0.m_pMemoryMap->InsertReadMap(0x00001000, 0x00001FFF, m_vuMem0, 0x02); m_VU0.m_pMemoryMap->InsertReadMap(0x00001000, 0x00001FFF, m_vuMem0, 0x02);
m_VU0.m_pMemoryMap->InsertReadMap(0x00002000, 0x00002FFF, m_vuMem0, 0x03); m_VU0.m_pMemoryMap->InsertReadMap(0x00002000, 0x00002FFF, m_vuMem0, 0x03);
@ -116,6 +121,8 @@ CSubSystem::CSubSystem(uint8* iopRam, CIopBios& iopBios)
//Vector Unit 1 context setup //Vector Unit 1 context setup
{ {
m_VU1.m_executor = std::make_unique<CVuExecutor>(m_VU1, PS2::MICROMEM1SIZE);
m_VU1.m_pMemoryMap->InsertReadMap(0x00000000, 0x00003FFF, m_vuMem1, 0x00); m_VU1.m_pMemoryMap->InsertReadMap(0x00000000, 0x00003FFF, m_vuMem1, 0x00);
m_VU1.m_pMemoryMap->InsertReadMap(0x00008000, 0x00008FFF, std::bind(&CSubSystem::Vu1IoPortReadHandler, this, PLACEHOLDER_1), 0x01); m_VU1.m_pMemoryMap->InsertReadMap(0x00008000, 0x00008FFF, std::bind(&CSubSystem::Vu1IoPortReadHandler, this, PLACEHOLDER_1), 0x01);
@ -147,7 +154,7 @@ CSubSystem::CSubSystem(uint8* iopRam, CIopBios& iopBios)
CSubSystem::~CSubSystem() CSubSystem::~CSubSystem()
{ {
m_executor.Reset(); m_EE.m_executor->Reset();
delete m_os; delete m_os;
framework_aligned_free(m_ram); framework_aligned_free(m_ram);
delete[] m_bios; delete[] m_bios;
@ -172,7 +179,7 @@ void CSubSystem::SetVpu1(std::shared_ptr<CVpu> newVpu1)
void CSubSystem::Reset() void CSubSystem::Reset()
{ {
m_os->Release(); m_os->Release();
m_executor.Reset(); m_EE.m_executor->Reset();
memset(m_ram, 0, PS2::EE_RAM_SIZE); memset(m_ram, 0, PS2::EE_RAM_SIZE);
memset(m_spr, 0, PS2::EE_SPR_SIZE); memset(m_spr, 0, PS2::EE_SPR_SIZE);
@ -228,7 +235,7 @@ int CSubSystem::ExecuteCpu(int quota)
} }
else if(!m_EE.m_State.nHasException) else if(!m_EE.m_State.nHasException)
{ {
executed = (quota - m_executor.Execute(quota)); executed = (quota - m_EE.m_executor->Execute(quota));
} }
if(m_EE.m_State.nHasException) if(m_EE.m_State.nHasException)
{ {
@ -380,7 +387,7 @@ void CSubSystem::LoadState(Framework::CZipArchiveReader& archive)
m_timer.LoadState(archive); m_timer.LoadState(archive);
m_gif.LoadState(archive); m_gif.LoadState(archive);
m_executor.Reset(); m_EE.m_executor->Reset();
} }
uint32 CSubSystem::IOPortReadHandler(uint32 nAddress) uint32 CSubSystem::IOPortReadHandler(uint32 nAddress)
@ -652,7 +659,7 @@ void CSubSystem::CheckPendingInterrupts()
m_intc.IsInterruptPending() m_intc.IsInterruptPending()
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
// && !m_singleStepEe // && !m_singleStepEe
&& !m_executor.MustBreak() && !m_EE.m_executor->MustBreak()
#endif #endif
) )
{ {
@ -663,7 +670,7 @@ void CSubSystem::CheckPendingInterrupts()
void CSubSystem::FlushInstructionCache() void CSubSystem::FlushInstructionCache()
{ {
m_executor.Reset(); m_EE.m_executor->Reset();
} }
void CSubSystem::LoadBIOS() void CSubSystem::LoadBIOS()

View file

@ -3,7 +3,6 @@
#include "AlignedAlloc.h" #include "AlignedAlloc.h"
#include "../COP_SCU.h" #include "../COP_SCU.h"
#include "../COP_FPU.h" #include "../COP_FPU.h"
#include "EeExecutor.h"
#include "DMAC.h" #include "DMAC.h"
#include "GIF.h" #include "GIF.h"
#include "SIF.h" #include "SIF.h"
@ -66,7 +65,6 @@ namespace Ee
CMIPS m_EE; CMIPS m_EE;
CMIPS m_VU0; CMIPS m_VU0;
CMIPS m_VU1; CMIPS m_VU1;
CEeExecutor m_executor;
void* operator new(size_t allocSize) void* operator new(size_t allocSize)
{ {

View file

@ -18,7 +18,6 @@ CVpu::CVpu(unsigned int number, const VPUINIT& vpuInit, CGIF& gif, CINTC& intc,
, m_vuMemSize((number == 0) ? PS2::VUMEM0SIZE : PS2::VUMEM1SIZE) , m_vuMemSize((number == 0) ? PS2::VUMEM0SIZE : PS2::VUMEM1SIZE)
, m_ctx(vpuInit.context) , m_ctx(vpuInit.context)
, m_gif(gif) , m_gif(gif)
, m_executor(*vpuInit.context, (number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE)
, m_vuProfilerZone(CProfiler::GetInstance().RegisterZone("VU")) , m_vuProfilerZone(CProfiler::GetInstance().RegisterZone("VU"))
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
, m_microMemMiniState(new uint8[(number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE]) , m_microMemMiniState(new uint8[(number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE])
@ -45,7 +44,7 @@ void CVpu::Execute(int32 quota)
CProfilerZone profilerZone(m_vuProfilerZone); CProfilerZone profilerZone(m_vuProfilerZone);
#endif #endif
m_executor.Execute(quota); m_ctx->m_executor->Execute(quota);
if(m_ctx->m_State.nHasException) if(m_ctx->m_State.nHasException)
{ {
//E bit encountered //E bit encountered
@ -55,16 +54,6 @@ void CVpu::Execute(int32 quota)
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
bool CVpu::MustBreak() const
{
return m_executor.MustBreak();
}
void CVpu::DisableBreakpointsOnce()
{
m_executor.DisableBreakpointsOnce();
}
void CVpu::SaveMiniState() void CVpu::SaveMiniState()
{ {
memcpy(m_microMemMiniState, m_microMem, (m_number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE); memcpy(m_microMemMiniState, m_microMem, (m_number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE);
@ -104,7 +93,7 @@ uint32 CVpu::GetVuItopMiniState() const
void CVpu::Reset() void CVpu::Reset()
{ {
m_running = false; m_running = false;
m_executor.Reset(); m_ctx->m_executor->Reset();
m_vif->Reset(); m_vif->Reset();
} }
@ -171,7 +160,7 @@ void CVpu::ExecuteMicroProgram(uint32 nAddress)
void CVpu::InvalidateMicroProgram() void CVpu::InvalidateMicroProgram()
{ {
m_executor.ClearActiveBlocksInRange(0, (m_number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE); m_ctx->m_executor->ClearActiveBlocksInRange(0, (m_number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE);
} }
void CVpu::ProcessXgKick(uint32 address) void CVpu::ProcessXgKick(uint32 address)

View file

@ -3,7 +3,6 @@
#include "Types.h" #include "Types.h"
#include "../MIPS.h" #include "../MIPS.h"
#include "../Profiler.h" #include "../Profiler.h"
#include "VuExecutor.h"
#include "Convertible.h" #include "Convertible.h"
#include "zip/ZipArchiveWriter.h" #include "zip/ZipArchiveWriter.h"
#include "zip/ZipArchiveReader.h" #include "zip/ZipArchiveReader.h"
@ -59,9 +58,6 @@ public:
void ProcessXgKick(uint32); void ProcessXgKick(uint32);
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
bool MustBreak() const;
void DisableBreakpointsOnce();
void SaveMiniState(); void SaveMiniState();
const MIPSSTATE& GetVuMiniState() const; const MIPSSTATE& GetVuMiniState() const;
uint8* GetVuMemoryMiniState() const; uint8* GetVuMemoryMiniState() const;
@ -89,7 +85,6 @@ protected:
#endif #endif
unsigned int m_number = 0; unsigned int m_number = 0;
CVuExecutor m_executor;
bool m_running = false; bool m_running = false;
CProfiler::ZoneHandle m_vuProfilerZone = 0; CProfiler::ZoneHandle m_vuProfilerZone = 0;

View file

@ -3,14 +3,14 @@
#include <zlib.h> #include <zlib.h>
CVuExecutor::CVuExecutor(CMIPS& context, uint32 maxAddress) CVuExecutor::CVuExecutor(CMIPS& context, uint32 maxAddress)
: CMipsExecutor(context, maxAddress) : CGenericMipsExecutor(context, maxAddress)
{ {
} }
void CVuExecutor::Reset() void CVuExecutor::Reset()
{ {
m_cachedBlocks.clear(); m_cachedBlocks.clear();
CMipsExecutor::Reset(); CGenericMipsExecutor::Reset();
} }
BasicBlockPtr CVuExecutor::BlockFactory(CMIPS& context, uint32 begin, uint32 end) BasicBlockPtr CVuExecutor::BlockFactory(CMIPS& context, uint32 begin, uint32 end)

View file

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <unordered_map> #include <unordered_map>
#include "../MipsExecutor.h" #include "../GenericMipsExecutor.h"
class CVuExecutor : public CMipsExecutor<BlockLookupOneWay> class CVuExecutor : public CGenericMipsExecutor<BlockLookupOneWay>
{ {
public: public:
CVuExecutor(CMIPS&, uint32); CVuExecutor(CMIPS&, uint32);

View file

@ -77,9 +77,8 @@
//This is the space needed to preserve at most four arguments in the stack frame (as per MIPS calling convention) //This is the space needed to preserve at most four arguments in the stack frame (as per MIPS calling convention)
#define STACK_FRAME_RESERVE_SIZE 0x10 #define STACK_FRAME_RESERVE_SIZE 0x10
CIopBios::CIopBios(CMIPS& cpu, CIopExecutor& cpuExecutor, uint8* ram, uint32 ramSize, uint8* spr) CIopBios::CIopBios(CMIPS& cpu, uint8* ram, uint32 ramSize, uint8* spr)
: m_cpu(cpu) : m_cpu(cpu)
, m_cpuExecutor(cpuExecutor)
, m_ram(ram) , m_ram(ram)
, m_ramSize(ramSize) , m_ramSize(ramSize)
, m_spr(spr) , m_spr(spr)
@ -661,7 +660,7 @@ int32 CIopBios::UnloadModule(uint32 loadedModuleId)
//TODO: Remove module from IOP module list? //TODO: Remove module from IOP module list?
//TODO: Invalidate MIPS analysis range? //TODO: Invalidate MIPS analysis range?
m_cpuExecutor.ClearActiveBlocksInRange(loadedModule->start, loadedModule->end); m_cpu.m_executor->ClearActiveBlocksInRange(loadedModule->start, loadedModule->end);
//TODO: Check return value here. //TODO: Check return value here.
m_sysmem->FreeMemory(loadedModule->start); m_sysmem->FreeMemory(loadedModule->start);

View file

@ -7,7 +7,6 @@
#include "../ELF.h" #include "../ELF.h"
#include "../OsStructManager.h" #include "../OsStructManager.h"
#include "../OsVariableWrapper.h" #include "../OsVariableWrapper.h"
#include "IopExecutor.h"
#include "Iop_BiosBase.h" #include "Iop_BiosBase.h"
#include "Iop_BiosStructs.h" #include "Iop_BiosStructs.h"
#include "Iop_SifMan.h" #include "Iop_SifMan.h"
@ -126,7 +125,7 @@ public:
uint32 reserved[4]; uint32 reserved[4];
}; };
CIopBios(CMIPS&, CIopExecutor&, uint8*, uint32, uint8*); CIopBios(CMIPS&, uint8*, uint32, uint8*);
virtual ~CIopBios(); virtual ~CIopBios();
int32 LoadModule(const char*); int32 LoadModule(const char*);
@ -516,7 +515,6 @@ private:
#endif #endif
CMIPS& m_cpu; CMIPS& m_cpu;
CIopExecutor& m_cpuExecutor;
uint8* m_ram = nullptr; uint8* m_ram = nullptr;
uint32 m_ramSize; uint32 m_ramSize;
uint8* m_spr = nullptr; uint8* m_spr = nullptr;

View file

@ -1,5 +0,0 @@
#pragma once
#include "../MipsExecutor.h"
typedef CMipsExecutor<BlockLookupOneWay> CIopExecutor;

View file

@ -1,5 +1,6 @@
#include "Iop_SubSystem.h" #include "Iop_SubSystem.h"
#include "IopBios.h" #include "IopBios.h"
#include "GenericMipsExecutor.h"
#include "../psx/PsxBios.h" #include "../psx/PsxBios.h"
#include "../MemoryStateFile.h" #include "../MemoryStateFile.h"
#include "../Ps2Const.h" #include "../Ps2Const.h"
@ -18,7 +19,6 @@ using namespace PS2;
CSubSystem::CSubSystem(bool ps2Mode) CSubSystem::CSubSystem(bool ps2Mode)
: m_cpu(MEMORYMAP_ENDIAN_LSBF) : m_cpu(MEMORYMAP_ENDIAN_LSBF)
, m_executor(m_cpu, (IOP_RAM_SIZE * 4))
, m_ram(new uint8[IOP_RAM_SIZE]) , m_ram(new uint8[IOP_RAM_SIZE])
, m_scratchPad(new uint8[IOP_SCRATCH_SIZE]) , m_scratchPad(new uint8[IOP_SCRATCH_SIZE])
, m_spuRam(new uint8[SPU_RAM_SIZE]) , m_spuRam(new uint8[SPU_RAM_SIZE])
@ -37,13 +37,15 @@ CSubSystem::CSubSystem(bool ps2Mode)
{ {
if(ps2Mode) if(ps2Mode)
{ {
m_bios = std::make_shared<CIopBios>(m_cpu, m_executor, m_ram, PS2::IOP_RAM_SIZE, m_scratchPad); m_bios = std::make_shared<CIopBios>(m_cpu, m_ram, PS2::IOP_RAM_SIZE, m_scratchPad);
} }
else else
{ {
m_bios = std::make_shared<CPsxBios>(m_cpu, m_ram, PS2::IOP_RAM_SIZE); m_bios = std::make_shared<CPsxBios>(m_cpu, m_ram, PS2::IOP_RAM_SIZE);
} }
m_cpu.m_executor = std::make_unique<CGenericMipsExecutor<BlockLookupOneWay>>(m_cpu, (IOP_RAM_SIZE * 4));
//Read memory map //Read memory map
m_cpu.m_pMemoryMap->InsertReadMap((0 * IOP_RAM_SIZE), (0 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x01); m_cpu.m_pMemoryMap->InsertReadMap((0 * IOP_RAM_SIZE), (0 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x01);
m_cpu.m_pMemoryMap->InsertReadMap((1 * IOP_RAM_SIZE), (1 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x02); m_cpu.m_pMemoryMap->InsertReadMap((1 * IOP_RAM_SIZE), (1 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x02);
@ -133,8 +135,8 @@ void CSubSystem::Reset()
memset(m_ram, 0, IOP_RAM_SIZE); memset(m_ram, 0, IOP_RAM_SIZE);
memset(m_scratchPad, 0, IOP_SCRATCH_SIZE); memset(m_scratchPad, 0, IOP_SCRATCH_SIZE);
memset(m_spuRam, 0, SPU_RAM_SIZE); memset(m_spuRam, 0, SPU_RAM_SIZE);
m_executor.Reset();
m_cpu.Reset(); m_cpu.Reset();
m_cpu.m_executor->Reset();
m_cpu.m_analysis->Clear(); m_cpu.m_analysis->Clear();
m_spuCore0.Reset(); m_spuCore0.Reset();
m_spuCore1.Reset(); m_spuCore1.Reset();
@ -302,7 +304,7 @@ int CSubSystem::ExecuteCpu(int quota)
CheckPendingInterrupts(); CheckPendingInterrupts();
if(!m_cpu.m_State.nHasException) if(!m_cpu.m_State.nHasException)
{ {
executed = (quota - m_executor.Execute(quota)); executed = (quota - m_cpu.m_executor->Execute(quota));
} }
if(m_cpu.m_State.nHasException) if(m_cpu.m_State.nHasException)
{ {

View file

@ -3,7 +3,6 @@
#include "../MIPS.h" #include "../MIPS.h"
#include "../MA_MIPSIV.h" #include "../MA_MIPSIV.h"
#include "../COP_SCU.h" #include "../COP_SCU.h"
#include "IopExecutor.h"
#include "Iop_SpuBase.h" #include "Iop_SpuBase.h"
#include "Iop_Spu.h" #include "Iop_Spu.h"
#include "Iop_Spu2.h" #include "Iop_Spu2.h"
@ -50,7 +49,6 @@ namespace Iop
CMIPS m_cpu; CMIPS m_cpu;
CMA_MIPSIV m_cpuArch; CMA_MIPSIV m_cpuArch;
CCOP_SCU m_copScu; CCOP_SCU m_copScu;
CIopExecutor m_executor;
BiosBasePtr m_bios; BiosBasePtr m_bios;
private: private:

View file

@ -125,12 +125,12 @@ void CPsfSubSystem::Update(bool singleStep, CSoundHandler* soundHandler)
bool CPsfSubSystem::MustBreak() bool CPsfSubSystem::MustBreak()
{ {
return m_iop.m_executor.MustBreak(); return m_iop.m_cpu.m_executor->MustBreak();
} }
void CPsfSubSystem::DisableBreakpointsOnce() void CPsfSubSystem::DisableBreakpointsOnce()
{ {
m_iop.m_executor.DisableBreakpointsOnce(); m_iop.m_cpu.m_executor->DisableBreakpointsOnce();
} }
CBiosDebugInfoProvider* CPsfSubSystem::GetBiosDebugInfoProvider() CBiosDebugInfoProvider* CPsfSubSystem::GetBiosDebugInfoProvider()

View file

@ -1,4 +1,5 @@
#include "Psp_PsfSubSystem.h" #include "Psp_PsfSubSystem.h"
#include "GenericMipsExecutor.h"
#include <thread> #include <thread>
using namespace Psp; using namespace Psp;
@ -12,11 +13,12 @@ CPsfSubSystem::CPsfSubSystem(uint32 ramSize)
, m_cpu(MEMORYMAP_ENDIAN_LSBF) , m_cpu(MEMORYMAP_ENDIAN_LSBF)
, m_copScu(MIPS_REGSIZE_32) , m_copScu(MIPS_REGSIZE_32)
, m_copFpu(MIPS_REGSIZE_32) , m_copFpu(MIPS_REGSIZE_32)
, m_executor(m_cpu, ramSize)
, m_spuCore0(m_spuRam, SPURAMSIZE, 0) , m_spuCore0(m_spuRam, SPURAMSIZE, 0)
, m_spuCore1(m_spuRam, SPURAMSIZE, 1) , m_spuCore1(m_spuRam, SPURAMSIZE, 1)
, m_bios(m_cpu, m_ram, ramSize) , m_bios(m_cpu, m_ram, ramSize)
{ {
m_cpu.m_executor = std::make_unique<CGenericMipsExecutor<BlockLookupTwoWay>>(m_cpu, ramSize);
//Read memory map //Read memory map
m_cpu.m_pMemoryMap->InsertReadMap(0x00000000, m_ramSize, m_ram, 0x01); m_cpu.m_pMemoryMap->InsertReadMap(0x00000000, m_ramSize, m_ram, 0x01);
@ -44,7 +46,7 @@ void CPsfSubSystem::Reset()
{ {
memset(m_ram, 0, m_ramSize); memset(m_ram, 0, m_ramSize);
memset(m_spuRam, 0, SPURAMSIZE); memset(m_spuRam, 0, SPURAMSIZE);
m_executor.Reset(); m_cpu.m_executor->Reset();
m_bios.Reset(); m_bios.Reset();
m_audioStream.Truncate(); m_audioStream.Truncate();
@ -78,7 +80,7 @@ Iop::CSpuBase& CPsfSubSystem::GetSpuCore(unsigned int coreId)
int CPsfSubSystem::ExecuteCpu(bool singleStep) int CPsfSubSystem::ExecuteCpu(bool singleStep)
{ {
int ticks = m_executor.Execute(singleStep ? 1 : 100); int ticks = m_cpu.m_executor->Execute(singleStep ? 1 : 100);
if(m_cpu.m_State.nHasException) if(m_cpu.m_State.nHasException)
{ {
m_bios.HandleException(); m_bios.HandleException();
@ -132,12 +134,12 @@ void CPsfSubSystem::Update(bool singleStep, CSoundHandler* soundHandler)
bool CPsfSubSystem::MustBreak() bool CPsfSubSystem::MustBreak()
{ {
return m_executor.MustBreak(); return m_cpu.m_executor->MustBreak();
} }
void CPsfSubSystem::DisableBreakpointsOnce() void CPsfSubSystem::DisableBreakpointsOnce()
{ {
m_executor.DisableBreakpointsOnce(); m_cpu.m_executor->DisableBreakpointsOnce();
} }
CBiosDebugInfoProvider* CPsfSubSystem::GetBiosDebugInfoProvider() CBiosDebugInfoProvider* CPsfSubSystem::GetBiosDebugInfoProvider()

View file

@ -6,15 +6,12 @@
#include "COP_SCU.h" #include "COP_SCU.h"
#include "COP_FPU.h" #include "COP_FPU.h"
#include "MIPS.h" #include "MIPS.h"
#include "MipsExecutor.h"
#include "../PsfVmSubSystem.h" #include "../PsfVmSubSystem.h"
#include "Psp_PsfBios.h" #include "Psp_PsfBios.h"
#include "MemStream.h" #include "MemStream.h"
namespace Psp namespace Psp
{ {
typedef CMipsExecutor<BlockLookupTwoWay> CPspExecutor;
class CPsfSubSystem : public CPsfVmSubSystem class CPsfSubSystem : public CPsfVmSubSystem
{ {
public: public:
@ -51,7 +48,6 @@ namespace Psp
int ExecuteCpu(bool); int ExecuteCpu(bool);
CMIPS m_cpu; CMIPS m_cpu;
CPspExecutor m_executor;
CMA_ALLEGREX m_cpuArch; CMA_ALLEGREX m_cpuArch;
CCOP_SCU m_copScu; CCOP_SCU m_copScu;
CCOP_FPU m_copFpu; CCOP_FPU m_copFpu;