Play-/Source/BlockLookupTwoWay.h
Jean-Philip Desjardins 050bf0f854 MipsExecutor is now owned by MIPS CPU context.
Will help to make new breakpoint implementation simpler.
2018-07-26 21:38:16 -04:00

103 lines
2.4 KiB
C++

#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;
};