AppleSAWS/src/internals/JumpLineManager.cpp

174 lines
4.6 KiB
C++

#include "JumpLineManager.h"
JumpLineManager::JumpLineManager(quint16 from, quint16 to)
: m_start(from),
m_end(to)
{
//qDebug() << "JumpLineManager(from:"<<uint16ToHex(m_start)<<", to:"<<uint16ToHex(m_end) << ")";
}
void JumpLineManager::addJump(quint16 src, quint16 dest, JumpType type, quint16 from, quint16 to)
{
TJump jump(src,dest);
if (src >= from && src <= to && dest >= from && dest <= to)
{
if (!m_jumpmap.contains(jump))
{
// qDebug() << "JumpLineManager::addJump: Added Jump from" << uint16ToHex(src) << "to" << uint16ToHex(dest) << ", Type:" << type;
m_jumpmap.insert(jump,type);
}
else
{
//qDebug() << "JumpLineManager::addJump: Not adding duplicate jump:" << uint16ToHex(src) << "," << uint16ToHex(dest);
}
}
else
{
// qDebug() << "JumpLineManager::addJump: Address range is out of bounds";
}
}
void JumpLineManager::dumpJumps() const {
dumpJumps(m_jumpmap);
}
void JumpLineManager::dumpJumps(JumpMap map) const
{
//qDebug() << "JumpLineManager::dumpJumps()\n JumpTable:";
QMapIterator<TJump,JumpType> it(map);
while (it.hasNext())
{
it.next();
QString jumptypelabel;
if (it.value() == IsUnknownJump) { jumptypelabel = "Unknown Jump"; }
if (it.value() == IsJMP) { jumptypelabel = "JMP"; }
if (it.value() == IsBranch) { jumptypelabel = "Branch"; }
if (it.value() == IsJSR) { jumptypelabel = "JSR"; }
if (it.value() == IsBRA) { jumptypelabel = "BRA"; }
//qDebug() << " Jump from" << uint16ToHex(it.key().first) << "to"
// << uint16ToHex(it.key().second) << jumptypelabel;
}
}
JumpLines JumpLineManager::buildJumpLines()
{
//qDebug() << "A";
m_channelsAtAddress.clear();
m_jumplines.m_maxChannel = 0;
QMapIterator<TJump, JumpType> it(m_jumpmap);
while (it.hasNext())
{
it.next();
TJump range = it.key();
JumpLine jl;
jl.type = it.value();
jl.from = range.first;
jl.to = range.second;
int channel = findBestChannel(jl);
setChannelForJumpLine(channel,jl);
m_jumplines.jumpLines.append(jl);
m_jumplines.m_maxChannel = qMax(m_jumplines.m_maxChannel, channel);
}
//qDebug() << "A";
return m_jumplines;
}
int JumpLineManager::findBestChannel(JumpLine &jl)
{
//qDebug() << "findBestChannel()";
if (m_jumplines.jumpLines.count() == 0)
{
return 0;
}
int potentialChannel = 0;
bool foundChannel = false;
while (!foundChannel)
{
//qDebug() << "Tryning potential channel" << potentialChannel;
bool matched = false;
for (quint16 addr = jl.min(); addr <= jl.max(); addr++)
{
// If any of these addresses contain the potential channel, move on
if (m_channelsAtAddress[addr].contains(potentialChannel))
{
matched = true;
}
}
if (matched)
{
potentialChannel++;
matched = false;
}
else
{
foundChannel = true;
}
}
return potentialChannel;
}
void JumpLineManager::setChannelForJumpLine(int channel, JumpLine &jl)
{
jl.channel = channel;
for (quint16 addr = jl.min(); addr <= jl.max(); addr++)
{
m_channelsAtAddress[addr].append(channel);
}
}
void JumpLineManager::dumpJumpLines() const
{
//foreach (JumpLine jl, m_jumplines.jumpLines)
// {
//qDebug() << " JumpLine from:" << uint16ToHex(jl.from)
// << " to:" << uint16ToHex(jl.to)
// << "channel: " << jl.channel << " type:" << jl.type;
// }
}
bool JumpLineManager::doJumpsIntersect(TJump &A, TJump &B) const
{
if (A == B) return false;
if (isLineWithinRange(A.first,B) || isLineWithinRange(A.second,B))
return true;
if (isLineWithinRange(B.first,A) || isLineWithinRange(B.second,A))
return true;
return false;
}
bool JumpLineManager::isLineWithinRange(quint16 line, TJump &jm) const
{
quint16 min = qMin(jm.first,jm.second);
quint16 max = qMax(jm.first,jm.second);
return (line > min && line < max);
}
QList<JumpLine> JumpLines::jumpLinesAtAddress(quint16 addrs)
{
QList<JumpLine> list;
foreach (JumpLine jl, jumpLines)
{
if (addrs >= jl.min() && addrs <= jl.max())
{
list.append(jl);
}
}
return list;
}