Supermodel/Src/Debugger/AddressTable.h

156 lines
3.7 KiB
C++

/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** This file is part of Supermodel.
**
** Supermodel is free software: you can redistribute it and/or modify it under
** the terms of the GNU General Public License as published by the Free
** Software Foundation, either version 3 of the License, or (at your option)
** any later version.
**
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
** more details.
**
** You should have received a copy of the GNU General Public License along
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
**/
/*
* AddressTable.h
*/
#ifdef SUPERMODEL_DEBUGGER
#ifndef INCLUDED_ADDRESSTABLE_H
#define INCLUDED_ADDRESSTABLE_H
#include "Types.h"
#include <vector>
#include <algorithm>
#define TABLE_WIDTH 16
#define TABLE_SIZE (1 << TABLE_WIDTH)
#define TABLE_MASK (TABLE_SIZE - 1)
#define INDEX_SHIFT TABLE_WIDTH
#define NUM_TABLES (0x100000000ULL / TABLE_SIZE)
namespace Debugger
{
class CCPUDebug;
/*
* Base class for objects that reference an address, such as a label or a comment.
*/
class CAddressRef
{
protected:
CAddressRef(CCPUDebug *refCPU, UINT32 refAddr, UINT32 refSize = 1);
public:
CCPUDebug *cpu;
const UINT32 addr;
const UINT32 size;
const UINT32 addrEnd;
bool CheckAddr(UINT32 loc);
// TODO - implement operators
};
/*
* Class that holds a table of address references. It does so in an a memory-expensive manner but with the result that it
* performs better (hopefully!) as lookups are constant-time.
*/
class CAddressTable
{
private:
int m_count;
CAddressRef **m_tables[NUM_TABLES];
CAddressRef **GetTableNoCreate(UINT32 addr, int &tableIndex, unsigned &indexInTable);
CAddressRef **GetTableCreate(UINT32 addr, int &tableIndex, unsigned &indexInTable);
void CheckAndReleaseTable(int tableIndex);
public:
CAddressTable();
~CAddressTable();
bool IsEmpty();
void Clear();
CAddressRef *Get(UINT32 addr);
CAddressRef *Get(UINT32 addr, UINT32 size);
void Add(CAddressRef *value);
bool Remove(CAddressRef *value);
};
//
// Inlined methods
//
inline bool CAddressRef::CheckAddr(UINT32 loc)
{
return addr <= loc && loc <= addrEnd;
}
inline CAddressRef **CAddressTable::GetTableNoCreate(UINT32 addr, int &tableIndex, unsigned &indexInTable)
{
tableIndex = addr >> INDEX_SHIFT;
if (m_tables[tableIndex] == NULL)
return NULL;
indexInTable = addr & TABLE_MASK;
return m_tables[tableIndex];
}
inline CAddressRef *CAddressTable::Get(UINT32 addr)
{
int tableIndex;
unsigned indexInTable;
CAddressRef **table = GetTableNoCreate(addr, tableIndex, indexInTable);
if (table == NULL)
return NULL;
return table[indexInTable];
}
inline CAddressRef *CAddressTable::Get(UINT32 addr, UINT32 size)
{
int tableIndex;
unsigned indexInTable;
CAddressRef **table = GetTableNoCreate(addr, tableIndex, indexInTable);
for (UINT32 i = 0; i < size; i++)
{
if (table != NULL)
{
CAddressRef *ref = table[indexInTable];
if (ref != NULL)
return ref;
addr++;
if (indexInTable >= TABLE_SIZE - 1)
table = GetTableNoCreate(addr, tableIndex, indexInTable);
else
indexInTable++;
}
else
{
addr++;
table = GetTableNoCreate(addr, tableIndex, indexInTable);
}
}
return NULL;
}
}
#endif // INCLUDED_ADDRESSTABLE_H
#endif // SUPERMODEL_DEBUGGER