mirror of https://github.com/stella-emu/stella.git
started working on multi bank support for labels
This commit is contained in:
parent
b08bbd7f79
commit
3fbaff31c9
|
@ -61,6 +61,15 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
|
||||||
};
|
};
|
||||||
mySystemAddresses = LabelToAddr(sysCmp);
|
mySystemAddresses = LabelToAddr(sysCmp);
|
||||||
|
|
||||||
|
// Add compare for system addresses (incl. banks)
|
||||||
|
const auto lblCmp = [](const BankAddress& a, const BankAddress& b)
|
||||||
|
{
|
||||||
|
if(a.bank == b.bank)
|
||||||
|
return a.addr < b.addr;
|
||||||
|
return a.bank < b.bank;
|
||||||
|
};
|
||||||
|
myUserLabels = AddrToLabel(lblCmp);
|
||||||
|
|
||||||
// Add Zero-page RAM addresses
|
// Add Zero-page RAM addresses
|
||||||
for(uInt16 i = 0x80; i <= 0xFF; ++i)
|
for(uInt16 i = 0x80; i <= 0xFF; ++i)
|
||||||
{
|
{
|
||||||
|
@ -80,18 +89,27 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
|
||||||
BankInfo info;
|
BankInfo info;
|
||||||
info.size = std::min<size_t>(romSize, 4_KB);
|
info.size = std::min<size_t>(romSize, 4_KB);
|
||||||
for(uInt32 i = 0; i < myConsole.cartridge().romBankCount(); ++i)
|
for(uInt32 i = 0; i < myConsole.cartridge().romBankCount(); ++i)
|
||||||
|
{
|
||||||
|
info.bank = i;
|
||||||
myBankInfo.push_back(info);
|
myBankInfo.push_back(info);
|
||||||
|
}
|
||||||
|
|
||||||
for(uInt32 i = 0; i < myConsole.cartridge().ramBankCount(); ++i)
|
for(uInt32 i = 0; i < myConsole.cartridge().ramBankCount(); ++i)
|
||||||
|
{
|
||||||
|
info.bank = i;
|
||||||
myBankInfo.push_back(info);
|
myBankInfo.push_back(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
info.bank = 0;
|
||||||
info.size = 128; // ZP RAM
|
info.size = 128; // ZP RAM
|
||||||
myBankInfo.push_back(info);
|
myBankInfo.push_back(info);
|
||||||
|
|
||||||
// We know the address for the startup bank right now
|
// We know the address for the startup bank right now
|
||||||
myBankInfo[myConsole.cartridge().startBank()].addressList.push_front(
|
myBankInfo[myConsole.cartridge().startBank()].addressList.push_front(
|
||||||
myDebugger.dpeek(0xfffc));
|
myDebugger.dpeek(0xfffc));
|
||||||
addLabel("Start", myDebugger.dpeek(0xfffc, Device::DATA)); // TOOD: ::CODE???
|
addLabel("Start",
|
||||||
|
BankAddress(myConsole.cartridge().startBank(),
|
||||||
|
myDebugger.dpeek(0xfffc, Device::DATA))); // TOOD: ::CODE???
|
||||||
|
|
||||||
// Add system equates
|
// Add system equates
|
||||||
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
|
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
|
||||||
|
@ -339,7 +357,8 @@ bool CartDebug::fillDisassemblyList(BankInfo& info, uInt16 search)
|
||||||
myDisassembly.list.clear();
|
myDisassembly.list.clear();
|
||||||
myDisassembly.fieldwidth = 24 + myLabelLength;
|
myDisassembly.fieldwidth = 24 + myLabelLength;
|
||||||
DiStella distella(*this, myDisassembly.list, info, DiStella::settings,
|
DiStella distella(*this, myDisassembly.list, info, DiStella::settings,
|
||||||
myDisLabels, myDisDirectives, myReserved);
|
myDisLabels, myDisDirectives, myReserved,
|
||||||
|
myConsole.cartridge().romBankCount());
|
||||||
|
|
||||||
// Parts of the disassembly will be accessed later in different ways
|
// Parts of the disassembly will be accessed later in different ways
|
||||||
// We place those parts in separate maps, to speed up access
|
// We place those parts in separate maps, to speed up access
|
||||||
|
@ -569,20 +588,20 @@ int CartDebug::romBankCount() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartDebug::addLabel(const string& label, uInt16 address)
|
bool CartDebug::addLabel(const string& label, BankAddress bankAddr)
|
||||||
{
|
{
|
||||||
// Only user-defined labels can be added or redefined
|
// Only user-defined labels can be added or redefined
|
||||||
switch(addressType(address))
|
switch(addressType(bankAddr.addr))
|
||||||
{
|
{
|
||||||
case AddrType::TIA:
|
case AddrType::TIA:
|
||||||
case AddrType::IO:
|
case AddrType::IO:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
removeLabel(label);
|
removeLabel(label);
|
||||||
myUserAddresses.emplace(label, address);
|
myUserAddresses.emplace(label, bankAddr);
|
||||||
myUserLabels.emplace(address, label);
|
myUserLabels.emplace(bankAddr, label);
|
||||||
myLabelLength = std::max(myLabelLength, uInt16(label.size()));
|
myLabelLength = std::max(myLabelLength, uInt16(label.size()));
|
||||||
mySystem.setDirtyPage(address);
|
mySystem.setDirtyPage(bankAddr.addr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -600,7 +619,7 @@ bool CartDebug::removeLabel(const string& label)
|
||||||
myUserLabels.erase(iter2);
|
myUserLabels.erase(iter2);
|
||||||
|
|
||||||
// Erase the label itself
|
// Erase the label itself
|
||||||
mySystem.setDirtyPage(iter->second);
|
mySystem.setDirtyPage(iter->second.addr);
|
||||||
myUserAddresses.erase(iter);
|
myUserAddresses.erase(iter);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -609,16 +628,16 @@ bool CartDebug::removeLabel(const string& label)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
bool CartDebug::getLabel(ostream& buf, BankAddress bankAddr, bool isRead,
|
||||||
int places, bool isRam) const
|
int places, bool isRam) const
|
||||||
{
|
{
|
||||||
switch(addressType(addr))
|
switch(addressType(bankAddr.addr))
|
||||||
{
|
{
|
||||||
case AddrType::TIA:
|
case AddrType::TIA:
|
||||||
{
|
{
|
||||||
if(isRead)
|
if(isRead)
|
||||||
{
|
{
|
||||||
uInt16 a = addr & 0x0F, offset = addr & 0xFFF0;
|
uInt16 a = bankAddr.addr & 0x0F, offset = bankAddr.addr & 0xFFF0;
|
||||||
if(ourTIAMnemonicR[a])
|
if(ourTIAMnemonicR[a])
|
||||||
{
|
{
|
||||||
buf << ourTIAMnemonicR[a];
|
buf << ourTIAMnemonicR[a];
|
||||||
|
@ -626,11 +645,11 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
buf << "|$" << Base::HEX2 << offset;
|
buf << "|$" << Base::HEX2 << offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf << "$" << Base::HEX2 << addr;
|
buf << "$" << Base::HEX2 << bankAddr.addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uInt16 a = addr & 0x3F, offset = addr & 0xFFC0;
|
uInt16 a = bankAddr.addr & 0x3F, offset = bankAddr.addr & 0xFFC0;
|
||||||
if(ourTIAMnemonicW[a])
|
if(ourTIAMnemonicW[a])
|
||||||
{
|
{
|
||||||
buf << ourTIAMnemonicW[a];
|
buf << ourTIAMnemonicW[a];
|
||||||
|
@ -638,14 +657,14 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
buf << "|$" << Base::HEX2 << offset;
|
buf << "|$" << Base::HEX2 << offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf << "$" << Base::HEX2 << addr;
|
buf << "$" << Base::HEX2 << bankAddr.addr;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AddrType::IO:
|
case AddrType::IO:
|
||||||
{
|
{
|
||||||
uInt16 a = addr & 0xFF, offset = addr & 0xFD00;
|
uInt16 a = bankAddr.addr & 0xFF, offset = bankAddr.addr & 0xFD00;
|
||||||
if(a <= 0x97)
|
if(a <= 0x97)
|
||||||
{
|
{
|
||||||
if(ourIOMnemonic[a - 0x80])
|
if(ourIOMnemonic[a - 0x80])
|
||||||
|
@ -655,10 +674,10 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
buf << "|$" << Base::HEX2 << offset;
|
buf << "|$" << Base::HEX2 << offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf << "$" << Base::HEX2 << addr;
|
buf << "$" << Base::HEX2 << bankAddr.addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf << "$" << Base::HEX2 << addr;
|
buf << "$" << Base::HEX2 << bankAddr.addr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -668,12 +687,12 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
// RAM can use user-defined labels; otherwise we default to
|
// RAM can use user-defined labels; otherwise we default to
|
||||||
// standard mnemonics
|
// standard mnemonics
|
||||||
AddrToLabel::const_iterator iter;
|
AddrToLabel::const_iterator iter;
|
||||||
uInt16 a = addr & 0xFF, offset = addr & 0xFF00;
|
uInt16 a = bankAddr.addr & 0xFF, offset = bankAddr.addr & 0xFF00;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
// Search for nearest label
|
// Search for nearest label
|
||||||
for(uInt16 i = a; i >= 0x80; --i)
|
for(uInt16 i = a; i >= 0x80; --i)
|
||||||
if((iter = myUserLabels.find(i)) != myUserLabels.end())
|
if((iter = myUserLabels.find(BankAddress(i))) != myUserLabels.end())
|
||||||
{
|
{
|
||||||
buf << iter->second;
|
buf << iter->second;
|
||||||
if(a != i)
|
if(a != i)
|
||||||
|
@ -697,18 +716,18 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
AddrToLabel::const_iterator iter;
|
AddrToLabel::const_iterator iter;
|
||||||
|
|
||||||
// Search for nearest label
|
// Search for nearest label
|
||||||
for(uInt16 i = addr; i >= (addr & 0xf000); --i)
|
for(uInt16 i = bankAddr.addr; i >= (bankAddr.addr & 0xf000); --i)
|
||||||
if((iter = myUserLabels.find(i)) != myUserLabels.end())
|
if((iter = myUserLabels.find(BankAddress(bankAddr.bank, i))) != myUserLabels.end())
|
||||||
{
|
{
|
||||||
buf << iter->second;
|
buf << iter->second;
|
||||||
if(addr != i)
|
if(bankAddr.addr != i)
|
||||||
buf << "+$" << Base::HEX1 << (addr - i);
|
buf << "+$" << Base::HEX1 << (bankAddr.addr - i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto& iter = myUserLabels.find(addr);
|
const auto& iter = myUserLabels.find(bankAddr);
|
||||||
if(iter != myUserLabels.end())
|
if(iter != myUserLabels.end())
|
||||||
{
|
{
|
||||||
// TODO: detect and add SUBROUTINE in saved disassembly
|
// TODO: detect and add SUBROUTINE in saved disassembly
|
||||||
|
@ -723,13 +742,13 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
switch(places)
|
switch(places)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
buf << "$" << Base::HEX2 << addr;
|
buf << "$" << Base::HEX2 << bankAddr.addr;
|
||||||
return true;
|
return true;
|
||||||
case 4:
|
case 4:
|
||||||
buf << "$" << Base::HEX4 << addr;
|
buf << "$" << Base::HEX4 << bankAddr.addr;
|
||||||
return true;
|
return true;
|
||||||
case 8:
|
case 8:
|
||||||
buf << "$" << Base::HEX8 << addr;
|
buf << "$" << Base::HEX8 << bankAddr.addr;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -739,15 +758,41 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string CartDebug::getLabel(uInt16 addr, bool isRead, int places, bool isRam) const
|
bool CartDebug::getLabel(ostream& buf, int bank, int addr, bool isRead,
|
||||||
|
int places, bool isRam) const
|
||||||
|
{
|
||||||
|
return getLabel(buf, BankAddress(bank, addr), isRead, places, isRam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CartDebug::getLabel(ostream& buf, int addr, bool isRead,
|
||||||
|
int places, bool isRam) const
|
||||||
|
{
|
||||||
|
return getLabel(buf, BankAddress(addr), isRead, places, isRam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string CartDebug::getLabel(BankAddress bankAddr, bool isRead, int places, bool isRam) const
|
||||||
{
|
{
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
getLabel(buf, addr, isRead, places, isRam);
|
getLabel(buf, bankAddr, isRead, places, isRam);
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int CartDebug::getAddress(const string& label) const
|
string CartDebug::getLabel(int bank, int addr, bool isRead, int places, bool isRam) const
|
||||||
|
{
|
||||||
|
return getLabel(BankAddress(bank, addr), isRead, places, isRam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string CartDebug::getLabel(int addr, bool isRead, int places, bool isRam) const
|
||||||
|
{
|
||||||
|
return getLabel(BankAddress(addr), isRead, places, isRam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
CartDebug::BankAddress CartDebug::getAddress(const string& label) const
|
||||||
{
|
{
|
||||||
LabelToAddr::const_iterator iter;
|
LabelToAddr::const_iterator iter;
|
||||||
|
|
||||||
|
@ -756,7 +801,7 @@ int CartDebug::getAddress(const string& label) const
|
||||||
else if((iter = myUserAddresses.find(label)) != myUserAddresses.end())
|
else if((iter = myUserAddresses.find(label)) != myUserAddresses.end())
|
||||||
return iter->second;
|
return iter->second;
|
||||||
else
|
else
|
||||||
return -1;
|
return BankAddress(-1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -811,7 +856,7 @@ string CartDebug::loadListFile()
|
||||||
buf >> hex >> xx >> hex >> yy >> line >> eq;
|
buf >> hex >> xx >> hex >> yy >> line >> eq;
|
||||||
if(xx >= 0 && yy >= 0 && eq == '=')
|
if(xx >= 0 && yy >= 0 && eq == '=')
|
||||||
//myUserCLabels.emplace(xx*256+yy, line);
|
//myUserCLabels.emplace(xx*256+yy, line);
|
||||||
addLabel(line, xx * 256 + yy);
|
addLabel(line, BankAddress(xx * 256 + yy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -860,7 +905,7 @@ string CartDebug::loadSymbolFile()
|
||||||
// For now, we simply ignore constants completely
|
// For now, we simply ignore constants completely
|
||||||
//const auto& iter = myUserCLabels.find(value);
|
//const auto& iter = myUserCLabels.find(value);
|
||||||
//if(iter == myUserCLabels.end() || !BSPF::equalsIgnoreCase(label, iter->second))
|
//if(iter == myUserCLabels.end() || !BSPF::equalsIgnoreCase(label, iter->second))
|
||||||
const auto& iter = myUserLabels.find(value);
|
const auto& iter = myUserLabels.find(BankAddress(value));
|
||||||
if(iter == myUserLabels.end() || !BSPF::equalsIgnoreCase(label, iter->second))
|
if(iter == myUserLabels.end() || !BSPF::equalsIgnoreCase(label, iter->second))
|
||||||
{
|
{
|
||||||
// Check for period, and strip leading number
|
// Check for period, and strip leading number
|
||||||
|
@ -872,16 +917,16 @@ string CartDebug::loadSymbolFile()
|
||||||
|
|
||||||
if(iterA != myUserAddresses.end())
|
if(iterA != myUserAddresses.end())
|
||||||
// if short label already exists, move prefix to suffix and add long local label name
|
// if short label already exists, move prefix to suffix and add long local label name
|
||||||
addLabel(shortLabel + "." + label.substr(0, pos), value);
|
addLabel(shortLabel + "." + label.substr(0, pos), BankAddress(value));
|
||||||
else
|
else
|
||||||
addLabel(shortLabel, value);
|
addLabel(shortLabel, BankAddress(value));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// skip local macro labels
|
// skip local macro labels
|
||||||
pos = label.find_last_of('$');
|
pos = label.find_last_of('$');
|
||||||
if(pos == string::npos || pos != label.length() - 1)
|
if(pos == string::npos || pos != label.length() - 1)
|
||||||
addLabel(label, value);
|
addLabel(label, BankAddress(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1128,10 +1173,11 @@ string CartDebug::saveDisassembly(string path)
|
||||||
// Disassemble bank
|
// Disassemble bank
|
||||||
disasm.list.clear();
|
disasm.list.clear();
|
||||||
DiStella distella(*this, disasm.list, info, settings,
|
DiStella distella(*this, disasm.list, info, settings,
|
||||||
myDisLabels, myDisDirectives, myReserved);
|
myDisLabels, myDisDirectives, myReserved,
|
||||||
|
myConsole.cartridge().romBankCount());
|
||||||
|
|
||||||
if (myReserved.breakFound)
|
if (myReserved.breakFound)
|
||||||
addLabel("Break", myDebugger.dpeek(0xfffe));
|
addLabel("Break", BankAddress(bank, myDebugger.dpeek(0xfffe)));
|
||||||
|
|
||||||
buf << " SEG CODE\n";
|
buf << " SEG CODE\n";
|
||||||
|
|
||||||
|
@ -1308,7 +1354,7 @@ string CartDebug::saveDisassembly(string path)
|
||||||
bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (Device::DATA | Device::WRITE));
|
bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (Device::DATA | Device::WRITE));
|
||||||
|
|
||||||
if (myReserved.ZPRAM[addr - 0x80] &&
|
if (myReserved.ZPRAM[addr - 0x80] &&
|
||||||
myUserLabels.find(addr) == myUserLabels.end()) {
|
myUserLabels.find(BankAddress(addr)) == myUserLabels.end()) {
|
||||||
if (addLine)
|
if (addLine)
|
||||||
out << "\n";
|
out << "\n";
|
||||||
out << ALIGN(16) << ourZPMnemonic[addr - 0x80] << "= $"
|
out << ALIGN(16) << ourZPMnemonic[addr - 0x80] << "= $"
|
||||||
|
@ -1341,7 +1387,7 @@ string CartDebug::saveDisassembly(string path)
|
||||||
<< "; Non Locatable Labels\n"
|
<< "; Non Locatable Labels\n"
|
||||||
<< ";-----------------------------------------------------------\n\n";
|
<< ";-----------------------------------------------------------\n\n";
|
||||||
for(const auto& iter: myReserved.Label)
|
for(const auto& iter: myReserved.Label)
|
||||||
out << ALIGN(16) << iter.second << "= $" << iter.first << "\n";
|
out << ALIGN(16) << iter.second << "= $" << iter.first.addr << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(myUserLabels.size() > 0)
|
if(myUserLabels.size() > 0)
|
||||||
|
@ -1353,7 +1399,7 @@ string CartDebug::saveDisassembly(string path)
|
||||||
for(const auto& iter: myUserLabels)
|
for(const auto& iter: myUserLabels)
|
||||||
max_len = std::max(max_len, int(iter.second.size()));
|
max_len = std::max(max_len, int(iter.second.size()));
|
||||||
for(const auto& iter: myUserLabels)
|
for(const auto& iter: myUserLabels)
|
||||||
out << ALIGN(max_len) << iter.second << "= $" << iter.first << "\n";
|
out << ALIGN(max_len) << iter.second << "= $" << iter.first.addr << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// And finally, output the disassembly
|
// And finally, output the disassembly
|
||||||
|
|
|
@ -68,6 +68,20 @@ class CartDebug : public DebuggerSystem
|
||||||
enum class AddrType { TIA, IO, ZPRAM, ROM };
|
enum class AddrType { TIA, IO, ZPRAM, ROM };
|
||||||
AddrType addressType(uInt16 addr) const;
|
AddrType addressType(uInt16 addr) const;
|
||||||
|
|
||||||
|
struct BankAddress {
|
||||||
|
Int16 bank{0}; // -1 means undefined
|
||||||
|
uInt16 addr{0};
|
||||||
|
|
||||||
|
explicit BankAddress(Int16 _bank, uInt16 _addr)
|
||||||
|
: bank{_bank}, addr{_addr} { }
|
||||||
|
explicit BankAddress(uInt16 _addr)
|
||||||
|
: bank{0}, addr{_addr} { }
|
||||||
|
BankAddress(const BankAddress&) = default;
|
||||||
|
BankAddress& operator=(const BankAddress&) = default;
|
||||||
|
BankAddress(BankAddress&&) = default;
|
||||||
|
BankAddress& operator=(BankAddress&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CartDebug(Debugger& dbg, Console& console, const OSystem& osystem);
|
CartDebug(Debugger& dbg, Console& console, const OSystem& osystem);
|
||||||
~CartDebug() override = default;
|
~CartDebug() override = default;
|
||||||
|
@ -193,7 +207,7 @@ class CartDebug : public DebuggerSystem
|
||||||
Add a label and associated address.
|
Add a label and associated address.
|
||||||
Labels that reference either TIA or RIOT spaces will not be processed.
|
Labels that reference either TIA or RIOT spaces will not be processed.
|
||||||
*/
|
*/
|
||||||
bool addLabel(const string& label, uInt16 address);
|
bool addLabel(const string& label, BankAddress bankAddr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove the given label and its associated address.
|
Remove the given label and its associated address.
|
||||||
|
@ -211,11 +225,20 @@ class CartDebug : public DebuggerSystem
|
||||||
If places is not -1 and a label hasn't been defined, return a
|
If places is not -1 and a label hasn't been defined, return a
|
||||||
formatted hexidecimal address
|
formatted hexidecimal address
|
||||||
*/
|
*/
|
||||||
bool getLabel(ostream& buf, uInt16 addr, bool isRead,
|
bool getLabel(ostream& buf, BankAddress bankAddr, bool isRead,
|
||||||
int places = -1, bool isRam = false) const;
|
int places = -1, bool isRam = false) const;
|
||||||
string getLabel(uInt16 addr, bool isRead,
|
bool getLabel(ostream& buf, int bank, int addr, bool isRead,
|
||||||
|
int places = -1, bool isRam = false) const;
|
||||||
|
bool getLabel(ostream& buf, int addr, bool isRead,
|
||||||
|
int places = -1, bool isRam = false) const;
|
||||||
|
string getLabel(BankAddress bankAddr, bool isRead,
|
||||||
int places = -1, bool isRam = false) const;
|
int places = -1, bool isRam = false) const;
|
||||||
int getAddress(const string& label) const;
|
string getLabel(int bank, int addr, bool isRead,
|
||||||
|
int places = -1, bool isRam = false) const;
|
||||||
|
string getLabel(int addr, bool isRead,
|
||||||
|
int places = -1, bool isRam = false) const;
|
||||||
|
|
||||||
|
BankAddress getAddress(const string& label) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Load constants from list file (as generated by DASM).
|
Load constants from list file (as generated by DASM).
|
||||||
|
@ -269,8 +292,9 @@ class CartDebug : public DebuggerSystem
|
||||||
void AccessTypeAsString(ostream& buf, Device::AccessType type) const;
|
void AccessTypeAsString(ostream& buf, Device::AccessType type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using AddrToLabel = std::map<uInt16, string>;
|
using AddrToLabel = std::map<BankAddress, string,
|
||||||
using LabelToAddr = std::map<string, uInt16,
|
std::function<bool(const BankAddress&, const BankAddress&)>>;
|
||||||
|
using LabelToAddr = std::map<string, BankAddress,
|
||||||
std::function<bool(const string&, const string&)>>;
|
std::function<bool(const string&, const string&)>>;
|
||||||
|
|
||||||
using AddrTypeArray = std::array<uInt16, 0x1000>;
|
using AddrTypeArray = std::array<uInt16, 0x1000>;
|
||||||
|
@ -284,6 +308,7 @@ class CartDebug : public DebuggerSystem
|
||||||
using DirectiveList = std::list<DirectiveTag>;
|
using DirectiveList = std::list<DirectiveTag>;
|
||||||
|
|
||||||
struct BankInfo {
|
struct BankInfo {
|
||||||
|
Int16 bank; // bank number
|
||||||
uInt16 start{0}; // start of address space
|
uInt16 start{0}; // start of address space
|
||||||
uInt16 end{0}; // end of address space
|
uInt16 end{0}; // end of address space
|
||||||
uInt16 offset{0}; // ORG value
|
uInt16 offset{0}; // ORG value
|
||||||
|
|
|
@ -122,7 +122,7 @@ bool Debugger::start(const string& message, int address, bool read,
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << message;
|
buf << message;
|
||||||
if(address > -1)
|
if(address > -1)
|
||||||
buf << cartDebug().getLabel(address, read, 4);
|
buf << cartDebug().getLabel(CartDebug::BankAddress(address), read, 4);
|
||||||
dialog().message().setText(buf.str());
|
dialog().message().setText(buf.str());
|
||||||
dialog().message().setToolTip(toolTip);
|
dialog().message().setToolTip(toolTip);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -136,7 +136,7 @@ class EquateExpression : public Expression
|
||||||
public:
|
public:
|
||||||
EquateExpression(const string& label) : Expression(), myLabel{label} { }
|
EquateExpression(const string& label) : Expression(), myLabel{label} { }
|
||||||
Int32 evaluate() const override
|
Int32 evaluate() const override
|
||||||
{ return Debugger::debugger().cartDebug().getAddress(myLabel); }
|
{ return Debugger::debugger().cartDebug().getAddress(myLabel).addr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string myLabel;
|
string myLabel;
|
||||||
|
|
|
@ -244,9 +244,10 @@ int DebuggerParser::decipher_arg(const string& str)
|
||||||
else if(arg == "pc" || arg == ".") result = state.PC;
|
else if(arg == "pc" || arg == ".") result = state.PC;
|
||||||
else { // Not a special, must be a regular arg: check for label first
|
else { // Not a special, must be a regular arg: check for label first
|
||||||
const char* a = arg.c_str();
|
const char* a = arg.c_str();
|
||||||
result = debugger.cartDebug().getAddress(arg);
|
CartDebug::BankAddress bankAddr = debugger.cartDebug().getAddress(arg);
|
||||||
|
result = bankAddr.addr;
|
||||||
|
|
||||||
if(result < 0) { // if not label, must be a number
|
if(bankAddr.bank < 0) { // if not label, must be a number
|
||||||
if(bin) { // treat as binary
|
if(bin) { // treat as binary
|
||||||
result = 0;
|
result = 0;
|
||||||
while(*a != '\0') {
|
while(*a != '\0') {
|
||||||
|
@ -595,9 +596,11 @@ void DebuggerParser::listTraps(bool listCond)
|
||||||
|
|
||||||
if(hasCond)
|
if(hasCond)
|
||||||
commandResult << " " << names[i];
|
commandResult << " " << names[i];
|
||||||
commandResult << " " << debugger.cartDebug().getLabel(myTraps[i]->begin, true, 4);
|
commandResult << " "
|
||||||
|
<< debugger.cartDebug().getLabel(myTraps[i]->begin, true, 4);
|
||||||
if(myTraps[i]->begin != myTraps[i]->end)
|
if(myTraps[i]->begin != myTraps[i]->end)
|
||||||
commandResult << " " << debugger.cartDebug().getLabel(myTraps[i]->end, true, 4);
|
commandResult << " "
|
||||||
|
<< debugger.cartDebug().getLabel(myTraps[i]->end, true, 4);
|
||||||
commandResult << trapStatus(*myTraps[i]);
|
commandResult << trapStatus(*myTraps[i]);
|
||||||
commandResult << " + mirrors";
|
commandResult << " + mirrors";
|
||||||
if(i != (names.size() - 1)) commandResult << endl;
|
if(i != (names.size() - 1)) commandResult << endl;
|
||||||
|
@ -1034,7 +1037,7 @@ void DebuggerParser::executeDebugColors()
|
||||||
void DebuggerParser::executeDefine()
|
void DebuggerParser::executeDefine()
|
||||||
{
|
{
|
||||||
// TODO: check if label already defined?
|
// TODO: check if label already defined?
|
||||||
debugger.cartDebug().addLabel(argStrings[0], args[1]);
|
debugger.cartDebug().addLabel(argStrings[0], CartDebug::BankAddress(args[1]));
|
||||||
debugger.rom().invalidate();
|
debugger.rom().invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1530,14 +1533,14 @@ void DebuggerParser::executeListbreaks()
|
||||||
{
|
{
|
||||||
if(romBankCount == 1)
|
if(romBankCount == 1)
|
||||||
{
|
{
|
||||||
buf << debugger.cartDebug().getLabel(bp.addr, true, 4) << " ";
|
buf << debugger.cartDebug().getLabel(bp.bank, bp.addr, true, 4) << " ";
|
||||||
if(!(++count % 8)) buf << endl;
|
if(!(++count % 8)) buf << endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(count % 6)
|
if(count % 6)
|
||||||
buf << ", ";
|
buf << ", ";
|
||||||
buf << debugger.cartDebug().getLabel(bp.addr, true, 4);
|
buf << debugger.cartDebug().getLabel(bp.bank, bp.addr, true, 4);
|
||||||
if(bp.bank != 255)
|
if(bp.bank != 255)
|
||||||
buf << " #" << int(bp.bank);
|
buf << " #" << int(bp.bank);
|
||||||
else
|
else
|
||||||
|
|
|
@ -26,13 +26,16 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
|
||||||
CartDebug::BankInfo& info, const DiStella::Settings& s,
|
CartDebug::BankInfo& info, const DiStella::Settings& s,
|
||||||
CartDebug::AddrTypeArray& labels,
|
CartDebug::AddrTypeArray& labels,
|
||||||
CartDebug::AddrTypeArray& directives,
|
CartDebug::AddrTypeArray& directives,
|
||||||
CartDebug::ReservedEquates& reserved)
|
CartDebug::ReservedEquates& reserved,
|
||||||
|
int numBanks)
|
||||||
: myDbg{dbg},
|
: myDbg{dbg},
|
||||||
myList{list},
|
myList{list},
|
||||||
mySettings{s},
|
mySettings{s},
|
||||||
myReserved{reserved},
|
myReserved{reserved},
|
||||||
myLabels{labels},
|
myLabels{labels},
|
||||||
myDirectives{directives}
|
myDirectives{directives},
|
||||||
|
myBank(info.bank),
|
||||||
|
myNumBanks(numBanks)
|
||||||
{
|
{
|
||||||
bool resolve_code = mySettings.resolveCode;
|
bool resolve_code = mySettings.resolveCode;
|
||||||
CartDebug::AddressList& debuggerAddresses = info.addressList;
|
CartDebug::AddressList& debuggerAddresses = info.addressList;
|
||||||
|
@ -72,7 +75,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
|
||||||
disasm(myOffset, 2);
|
disasm(myOffset, 2);
|
||||||
|
|
||||||
// Add reserved line equates
|
// Add reserved line equates
|
||||||
ostringstream reservedLabel;
|
stringstream reservedLabel;
|
||||||
for (int k = 0; k <= myAppData.end; k++) {
|
for (int k = 0; k <= myAppData.end; k++) {
|
||||||
if ((myLabels[k] & (Device::REFERENCED | Device::VALID_ENTRY)) == Device::REFERENCED) {
|
if ((myLabels[k] & (Device::REFERENCED | Device::VALID_ENTRY)) == Device::REFERENCED) {
|
||||||
// If we have a piece of code referenced somewhere else, but cannot
|
// If we have a piece of code referenced somewhere else, but cannot
|
||||||
|
@ -82,7 +85,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
|
||||||
// However, we only do this for labels pointing to ROM (above $1000)
|
// However, we only do this for labels pointing to ROM (above $1000)
|
||||||
if (myDbg.addressType(k + myOffset) == CartDebug::AddrType::ROM) {
|
if (myDbg.addressType(k + myOffset) == CartDebug::AddrType::ROM) {
|
||||||
reservedLabel.str("");
|
reservedLabel.str("");
|
||||||
reservedLabel << "L" << Base::HEX4 << (k + myOffset);
|
labelHigh(reservedLabel, k + myOffset);
|
||||||
myReserved.Label.emplace(k + myOffset, reservedLabel.str());
|
myReserved.Label.emplace(k + myOffset, reservedLabel.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,8 +104,8 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
- pass 3 generates output
|
- pass 3 generates output
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
#define LABEL_A12_HIGH(address) labelA12High(nextLine, opcode, address, labelFound)
|
#define LABEL_HIGH(addr) labelHigh(nextLine, addr)
|
||||||
#define LABEL_A12_LOW(address) labelA12Low(nextLine, opcode, address, labelFound)
|
#define LABEL_LOW(addr) labelLow(nextLine, opcode, addr, labelFound)
|
||||||
|
|
||||||
uInt8 opcode, d1;
|
uInt8 opcode, d1;
|
||||||
uInt16 ad;
|
uInt16 ad;
|
||||||
|
@ -184,7 +187,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
|
|
||||||
// add extra spacing line when switching from non-code to code
|
// add extra spacing line when switching from non-code to code
|
||||||
if(pass == 3 && mySegType != Device::CODE && mySegType != Device::NONE) {
|
if(pass == 3 && mySegType != Device::CODE && mySegType != Device::NONE) {
|
||||||
myDisasmBuf << " ' ' ";
|
myDisasmBuf << EMPTY_LINE;
|
||||||
addEntry(Device::NONE);
|
addEntry(Device::NONE);
|
||||||
mark(myPC + myOffset, Device::REFERENCED); // add label when switching
|
mark(myPC + myOffset, Device::REFERENCED); // add label when switching
|
||||||
}
|
}
|
||||||
|
@ -201,9 +204,12 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
|
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
if(checkBit(myPC, Device::REFERENCED))
|
if(checkBit(myPC, Device::REFERENCED))
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'";
|
{
|
||||||
|
myDisasmBuf << Base::HEX4 << myPC + myOffset;
|
||||||
|
lineLabelHigh(myDisasmBuf, myPC + myOffset);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '";
|
myDisasmBuf << Base::HEX4 << myPC + myOffset << NO_LABEL;
|
||||||
}
|
}
|
||||||
++myPC;
|
++myPC;
|
||||||
|
|
||||||
|
@ -276,10 +282,14 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
addEntry(Device::DATA);
|
addEntry(Device::DATA);
|
||||||
|
|
||||||
if(myPC == myAppData.end) {
|
if(myPC == myAppData.end) {
|
||||||
|
|
||||||
if(checkBit(myPC, Device::REFERENCED))
|
if(checkBit(myPC, Device::REFERENCED))
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'";
|
{
|
||||||
|
myDisasmBuf << Base::HEX4 << myPC + myOffset;
|
||||||
|
lineLabelHigh(myDisasmBuf, myPC + myOffset);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '";
|
myDisasmBuf << Base::HEX4 << myPC + myOffset << NO_LABEL;
|
||||||
|
|
||||||
opcode = Debugger::debugger().peek(myPC + myOffset); ++myPC;
|
opcode = Debugger::debugger().peek(myPC + myOffset); ++myPC;
|
||||||
myDisasmBuf << ".byte $" << Base::HEX2 << int(opcode) << " $"
|
myDisasmBuf << ".byte $" << Base::HEX2 << int(opcode) << " $"
|
||||||
|
@ -338,13 +348,13 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
|
|
||||||
if(labelFound == AddressType::ROM) {
|
if(labelFound == AddressType::ROM) {
|
||||||
LABEL_A12_HIGH(ad);
|
LABEL_HIGH(ad);
|
||||||
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
||||||
}
|
}
|
||||||
else if(labelFound == AddressType::ROM_MIRROR) {
|
else if(labelFound == AddressType::ROM_MIRROR) {
|
||||||
if(mySettings.rFlag) {
|
if(mySettings.rFlag) {
|
||||||
int tmp = (ad & myAppData.end) + myOffset;
|
int tmp = (ad & myAppData.end) + myOffset;
|
||||||
LABEL_A12_HIGH(tmp);
|
LABEL_HIGH(tmp);
|
||||||
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
|
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -353,7 +363,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LABEL_A12_LOW(ad);
|
LABEL_LOW(ad);
|
||||||
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,7 +376,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
labelFound = mark(d1, Device::REFERENCED);
|
labelFound = mark(d1, Device::REFERENCED);
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
LABEL_A12_LOW(int(d1));
|
LABEL_LOW(int(d1));
|
||||||
nextLineBytes << Base::HEX2 << int(d1);
|
nextLineBytes << Base::HEX2 << int(d1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -400,14 +410,14 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
|
|
||||||
if(labelFound == AddressType::ROM) {
|
if(labelFound == AddressType::ROM) {
|
||||||
LABEL_A12_HIGH(ad);
|
LABEL_HIGH(ad);
|
||||||
nextLine << ",x";
|
nextLine << ",x";
|
||||||
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
||||||
}
|
}
|
||||||
else if(labelFound == AddressType::ROM_MIRROR) {
|
else if(labelFound == AddressType::ROM_MIRROR) {
|
||||||
if(mySettings.rFlag) {
|
if(mySettings.rFlag) {
|
||||||
int tmp = (ad & myAppData.end) + myOffset;
|
int tmp = (ad & myAppData.end) + myOffset;
|
||||||
LABEL_A12_HIGH(tmp);
|
LABEL_HIGH(tmp);
|
||||||
nextLine << ",x";
|
nextLine << ",x";
|
||||||
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
|
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
|
||||||
}
|
}
|
||||||
|
@ -417,7 +427,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LABEL_A12_LOW(ad);
|
LABEL_LOW(ad);
|
||||||
nextLine << ",x";
|
nextLine << ",x";
|
||||||
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
||||||
}
|
}
|
||||||
|
@ -443,14 +453,14 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
|
|
||||||
if(labelFound == AddressType::ROM) {
|
if(labelFound == AddressType::ROM) {
|
||||||
LABEL_A12_HIGH(ad);
|
LABEL_HIGH(ad);
|
||||||
nextLine << ",y";
|
nextLine << ",y";
|
||||||
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
||||||
}
|
}
|
||||||
else if(labelFound == AddressType::ROM_MIRROR) {
|
else if(labelFound == AddressType::ROM_MIRROR) {
|
||||||
if(mySettings.rFlag) {
|
if(mySettings.rFlag) {
|
||||||
int tmp = (ad & myAppData.end) + myOffset;
|
int tmp = (ad & myAppData.end) + myOffset;
|
||||||
LABEL_A12_HIGH(tmp);
|
LABEL_HIGH(tmp);
|
||||||
nextLine << ",y";
|
nextLine << ",y";
|
||||||
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
|
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
|
||||||
}
|
}
|
||||||
|
@ -460,7 +470,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LABEL_A12_LOW(ad);
|
LABEL_LOW(ad);
|
||||||
nextLine << ",y";
|
nextLine << ",y";
|
||||||
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
|
||||||
}
|
}
|
||||||
|
@ -474,7 +484,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
labelFound = mark(d1, 0); // dummy call to get address type
|
labelFound = mark(d1, 0); // dummy call to get address type
|
||||||
nextLine << " (";
|
nextLine << " (";
|
||||||
LABEL_A12_LOW(d1);
|
LABEL_LOW(d1);
|
||||||
nextLine << ",x)";
|
nextLine << ",x)";
|
||||||
nextLineBytes << Base::HEX2 << int(d1);
|
nextLineBytes << Base::HEX2 << int(d1);
|
||||||
}
|
}
|
||||||
|
@ -487,7 +497,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
labelFound = mark(d1, 0); // dummy call to get address type
|
labelFound = mark(d1, 0); // dummy call to get address type
|
||||||
nextLine << " (";
|
nextLine << " (";
|
||||||
LABEL_A12_LOW(d1);
|
LABEL_LOW(d1);
|
||||||
nextLine << "),y";
|
nextLine << "),y";
|
||||||
nextLineBytes << Base::HEX2 << int(d1);
|
nextLineBytes << Base::HEX2 << int(d1);
|
||||||
}
|
}
|
||||||
|
@ -500,7 +510,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
labelFound = mark(d1, Device::REFERENCED);
|
labelFound = mark(d1, Device::REFERENCED);
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
LABEL_A12_LOW(d1);
|
LABEL_LOW(d1);
|
||||||
nextLine << ",x";
|
nextLine << ",x";
|
||||||
}
|
}
|
||||||
nextLineBytes << Base::HEX2 << int(d1);
|
nextLineBytes << Base::HEX2 << int(d1);
|
||||||
|
@ -513,7 +523,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
labelFound = mark(d1, Device::REFERENCED);
|
labelFound = mark(d1, Device::REFERENCED);
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
LABEL_A12_LOW(d1);
|
LABEL_LOW(d1);
|
||||||
nextLine << ",y";
|
nextLine << ",y";
|
||||||
}
|
}
|
||||||
nextLineBytes << Base::HEX2 << int(d1);
|
nextLineBytes << Base::HEX2 << int(d1);
|
||||||
|
@ -532,7 +542,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
if(pass == 3) {
|
if(pass == 3) {
|
||||||
if(labelFound == AddressType::ROM) {
|
if(labelFound == AddressType::ROM) {
|
||||||
nextLine << " ";
|
nextLine << " ";
|
||||||
LABEL_A12_HIGH(ad);
|
LABEL_HIGH(ad);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nextLine << " $" << Base::HEX4 << ad;
|
nextLine << " $" << Base::HEX4 << ad;
|
||||||
|
@ -561,23 +571,23 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
}
|
}
|
||||||
if(labelFound == AddressType::ROM) {
|
if(labelFound == AddressType::ROM) {
|
||||||
nextLine << "(";
|
nextLine << "(";
|
||||||
LABEL_A12_HIGH(ad);
|
LABEL_HIGH(ad);
|
||||||
nextLine << ")";
|
nextLine << ")";
|
||||||
}
|
}
|
||||||
else if(labelFound == AddressType::ROM_MIRROR) {
|
else if(labelFound == AddressType::ROM_MIRROR) {
|
||||||
nextLine << "(";
|
nextLine << "(";
|
||||||
if(mySettings.rFlag) {
|
if(mySettings.rFlag) {
|
||||||
int tmp = (ad & myAppData.end) + myOffset;
|
int tmp = (ad & myAppData.end) + myOffset;
|
||||||
LABEL_A12_HIGH(tmp);
|
LABEL_HIGH(tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LABEL_A12_LOW(ad);
|
LABEL_LOW(ad);
|
||||||
}
|
}
|
||||||
nextLine << ")";
|
nextLine << ")";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nextLine << "(";
|
nextLine << "(";
|
||||||
LABEL_A12_LOW(ad);
|
LABEL_LOW(ad);
|
||||||
nextLine << ")";
|
nextLine << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,23 +604,27 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
// A complete line of disassembly (text, cycle count, and bytes)
|
// A complete line of disassembly (text, cycle count, and bytes)
|
||||||
myDisasmBuf << nextLine.str() << "'"
|
myDisasmBuf << nextLine.str() << "'"
|
||||||
<< ";" << std::dec << int(ourLookup[opcode].cycles)
|
<< ";" << std::dec << int(ourLookup[opcode].cycles)
|
||||||
<< (addrMode == AddressingMode::RELATIVE ? (ad & 0xf00) != ((myPC + myOffset) & 0xf00) ? "/3!" : "/3 " : " ");
|
<< (addrMode == AddressingMode::RELATIVE
|
||||||
|
? (ad & 0xf00) != ((myPC + myOffset) & 0xf00)
|
||||||
|
? "/3!" : "/3 "
|
||||||
|
: " ");
|
||||||
if((opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00 // code block end
|
if((opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00 // code block end
|
||||||
|| checkBit(myPC, Device::REFERENCED) // referenced address
|
|| checkBit(myPC, Device::REFERENCED) // referenced address
|
||||||
|| (ourLookup[opcode].rw_mode == RWMode::WRITE && d1 == WSYNC)) // strobe WSYNC
|
|| (ourLookup[opcode].rw_mode == RWMode::WRITE && d1 == WSYNC)) // strobe WSYNC
|
||||||
&& cycles > 0) {
|
&& cycles > 0) {
|
||||||
// output cycles for previous code block
|
// output cycles for previous code block
|
||||||
myDisasmBuf << "'= " << std::setw(3) << std::setfill(' ') << std::dec << cycles;
|
myDisasmBuf << "'= "
|
||||||
|
<< std::right << std::setw(3) << std::setfill(' ') << std::dec << cycles << "'";
|
||||||
cycles = 0;
|
cycles = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
myDisasmBuf << "' ";
|
myDisasmBuf << "' '";
|
||||||
}
|
}
|
||||||
myDisasmBuf << "'" << nextLineBytes.str();
|
myDisasmBuf << nextLineBytes.str();
|
||||||
|
|
||||||
addEntry(Device::CODE);
|
addEntry(Device::CODE);
|
||||||
if(opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00) {
|
if(opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00) {
|
||||||
myDisasmBuf << " ' ' ";
|
myDisasmBuf << EMPTY_LINE;
|
||||||
addEntry(Device::NONE);
|
addEntry(Device::NONE);
|
||||||
mySegType = Device::NONE; // prevent extra lines if data follows
|
mySegType = Device::NONE; // prevent extra lines if data follows
|
||||||
}
|
}
|
||||||
|
@ -1031,7 +1045,7 @@ void DiStella::addEntry(Device::AccessType type)
|
||||||
// Label (a user-defined label always overrides any auto-generated one)
|
// Label (a user-defined label always overrides any auto-generated one)
|
||||||
myDisasmBuf.seekg(5, std::ios::beg);
|
myDisasmBuf.seekg(5, std::ios::beg);
|
||||||
if (tag.address) {
|
if (tag.address) {
|
||||||
tag.label = myDbg.getLabel(tag.address, true);
|
tag.label = myDbg.getLabel(myBank, tag.address, true);
|
||||||
tag.hllabel = true;
|
tag.hllabel = true;
|
||||||
if (tag.label == EmptyString) {
|
if (tag.label == EmptyString) {
|
||||||
if (myDisasmBuf.peek() != ' ')
|
if (myDisasmBuf.peek() != ' ')
|
||||||
|
@ -1047,7 +1061,7 @@ void DiStella::addEntry(Device::AccessType type)
|
||||||
// Disassembly
|
// Disassembly
|
||||||
// Up to this point the field sizes are fixed, until we get to
|
// Up to this point the field sizes are fixed, until we get to
|
||||||
// variable length labels, cycle counts, etc
|
// variable length labels, cycle counts, etc
|
||||||
myDisasmBuf.seekg(11, std::ios::beg);
|
myDisasmBuf.seekg(11+3, std::ios::beg);
|
||||||
switch (tag.type) {
|
switch (tag.type) {
|
||||||
case Device::CODE:
|
case Device::CODE:
|
||||||
getline(myDisasmBuf, tag.disasm, '\'');
|
getline(myDisasmBuf, tag.disasm, '\'');
|
||||||
|
@ -1103,15 +1117,18 @@ void DiStella::outputGraphics()
|
||||||
|
|
||||||
// add extra spacing line when switching from non-graphics to graphics
|
// add extra spacing line when switching from non-graphics to graphics
|
||||||
if (mySegType != Device::GFX && mySegType != Device::NONE) {
|
if (mySegType != Device::GFX && mySegType != Device::NONE) {
|
||||||
myDisasmBuf << " ' ' ";
|
myDisasmBuf << EMPTY_LINE;
|
||||||
addEntry(Device::NONE);
|
addEntry(Device::NONE);
|
||||||
}
|
}
|
||||||
mySegType = Device::GFX;
|
mySegType = Device::GFX;
|
||||||
|
|
||||||
if (checkBit(myPC, Device::REFERENCED))
|
if (checkBit(myPC, Device::REFERENCED))
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'";
|
{
|
||||||
|
myDisasmBuf << Base::HEX4 << myPC + myOffset;
|
||||||
|
lineLabelHigh(myDisasmBuf, myPC + myOffset);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '";
|
myDisasmBuf << Base::HEX4 << myPC + myOffset << NO_LABEL;
|
||||||
myDisasmBuf << ".byte $" << Base::HEX2 << int(byte) << " |";
|
myDisasmBuf << ".byte $" << Base::HEX2 << int(byte) << " |";
|
||||||
for (uInt8 i = 0, c = byte; i < 8; ++i, c <<= 1)
|
for (uInt8 i = 0, c = byte; i < 8; ++i, c <<= 1)
|
||||||
myDisasmBuf << ((c > 127) ? bitString : " ");
|
myDisasmBuf << ((c > 127) ? bitString : " ");
|
||||||
|
@ -1149,16 +1166,19 @@ void DiStella::outputColors()
|
||||||
// add extra spacing line when switching from non-colors to colors
|
// add extra spacing line when switching from non-colors to colors
|
||||||
if(mySegType != Device::COL && mySegType != Device::NONE)
|
if(mySegType != Device::COL && mySegType != Device::NONE)
|
||||||
{
|
{
|
||||||
myDisasmBuf << " ' ' ";
|
myDisasmBuf << EMPTY_LINE;
|
||||||
addEntry(Device::NONE);
|
addEntry(Device::NONE);
|
||||||
}
|
}
|
||||||
mySegType = Device::COL;
|
mySegType = Device::COL;
|
||||||
|
|
||||||
// output label/address
|
// output label/address
|
||||||
if(checkBit(myPC, Device::REFERENCED))
|
if(checkBit(myPC, Device::REFERENCED))
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'";
|
{
|
||||||
|
myDisasmBuf << Base::HEX4 << myPC + myOffset;
|
||||||
|
lineLabelHigh(myDisasmBuf, myPC + myOffset);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '";
|
myDisasmBuf << Base::HEX4 << myPC + myOffset << NO_LABEL;
|
||||||
|
|
||||||
// output color
|
// output color
|
||||||
string color;
|
string color;
|
||||||
|
@ -1202,7 +1222,7 @@ void DiStella::outputBytes(Device::AccessType type)
|
||||||
|
|
||||||
// add extra spacing line when switching from non-data to data
|
// add extra spacing line when switching from non-data to data
|
||||||
if (mySegType != Device::DATA && mySegType != Device::NONE) {
|
if (mySegType != Device::DATA && mySegType != Device::NONE) {
|
||||||
myDisasmBuf << " ' ' ";
|
myDisasmBuf << EMPTY_LINE;
|
||||||
addEntry(Device::NONE);
|
addEntry(Device::NONE);
|
||||||
}
|
}
|
||||||
mySegType = Device::DATA;
|
mySegType = Device::DATA;
|
||||||
|
@ -1213,15 +1233,16 @@ void DiStella::outputBytes(Device::AccessType type)
|
||||||
if (!lineEmpty)
|
if (!lineEmpty)
|
||||||
addEntry(type);
|
addEntry(type);
|
||||||
|
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4
|
myDisasmBuf << Base::HEX4 << myPC + myOffset;
|
||||||
<< myPC + myOffset << "'.byte " << "$" << Base::HEX2
|
lineLabelHigh(myDisasmBuf, myPC + myOffset);
|
||||||
|
myDisasmBuf << ".byte " << "$" << Base::HEX2
|
||||||
<< int(Debugger::debugger().peek(myPC + myOffset));
|
<< int(Debugger::debugger().peek(myPC + myOffset));
|
||||||
++myPC;
|
++myPC;
|
||||||
numBytes = 1;
|
numBytes = 1;
|
||||||
lineEmpty = false;
|
lineEmpty = false;
|
||||||
} else if (lineEmpty) {
|
} else if (lineEmpty) {
|
||||||
// start a new line without a label
|
// start a new line without a label
|
||||||
myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '"
|
myDisasmBuf << Base::HEX4 << myPC + myOffset << NO_LABEL
|
||||||
<< ".byte $" << Base::HEX2 << int(Debugger::debugger().peek(myPC + myOffset));
|
<< ".byte $" << Base::HEX2 << int(Debugger::debugger().peek(myPC + myOffset));
|
||||||
++myPC;
|
++myPC;
|
||||||
numBytes = 1;
|
numBytes = 1;
|
||||||
|
@ -1243,7 +1264,7 @@ void DiStella::outputBytes(Device::AccessType type)
|
||||||
}
|
}
|
||||||
if (!lineEmpty)
|
if (!lineEmpty)
|
||||||
addEntry(type);
|
addEntry(type);
|
||||||
/*myDisasmBuf << " ' ' ";
|
/*myDisasmBuf << EMPTY_LINE;
|
||||||
addEntry(Device::NONE);*/
|
addEntry(Device::NONE);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1588,3 +1609,7 @@ const std::array<DiStella::Instruction_tag, 256> DiStella::ourLookup = { {
|
||||||
/* fe */{"inc", AddressingMode::ABSOLUTE_X, AccessMode::ABSX, RWMode::WRITE, 7, 3}, /* Absolute,X */
|
/* fe */{"inc", AddressingMode::ABSOLUTE_X, AccessMode::ABSX, RWMode::WRITE, 7, 3}, /* Absolute,X */
|
||||||
/* ff */{"ISB", AddressingMode::ABSOLUTE_X, AccessMode::ABSX, RWMode::WRITE, 7, 3}
|
/* ff */{"ISB", AddressingMode::ABSOLUTE_X, AccessMode::ABSX, RWMode::WRITE, 7, 3}
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
const string DiStella::NO_LABEL = "' '"; // 8 chars per address (was 5)
|
||||||
|
const string DiStella::EMPTY_LINE = " " + NO_LABEL + " ";
|
||||||
|
|
|
@ -65,12 +65,14 @@ class DiStella
|
||||||
@param labels Array storing label info determined by Distella
|
@param labels Array storing label info determined by Distella
|
||||||
@param directives Array storing directive info determined by Distella
|
@param directives Array storing directive info determined by Distella
|
||||||
@param reserved The TIA/RIOT addresses referenced in the disassembled code
|
@param reserved The TIA/RIOT addresses referenced in the disassembled code
|
||||||
|
@param numBank The total number of ROM banks
|
||||||
*/
|
*/
|
||||||
DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
|
DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
|
||||||
CartDebug::BankInfo& info, const DiStella::Settings& settings,
|
CartDebug::BankInfo& info, const DiStella::Settings& settings,
|
||||||
CartDebug::AddrTypeArray& labels,
|
CartDebug::AddrTypeArray& labels,
|
||||||
CartDebug::AddrTypeArray& directives,
|
CartDebug::AddrTypeArray& directives,
|
||||||
CartDebug::ReservedEquates& reserved);
|
CartDebug::ReservedEquates& reserved,
|
||||||
|
int numBanks);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
@ -86,6 +88,8 @@ class DiStella
|
||||||
ZP_RAM
|
ZP_RAM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const string NO_LABEL;
|
||||||
|
static const string EMPTY_LINE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Indicate that a new line of disassembly has been completed
|
// Indicate that a new line of disassembly has been completed
|
||||||
|
@ -111,12 +115,29 @@ class DiStella
|
||||||
void outputBytes(Device::AccessType type);
|
void outputBytes(Device::AccessType type);
|
||||||
|
|
||||||
// Convenience methods to generate appropriate labels
|
// Convenience methods to generate appropriate labels
|
||||||
inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound)
|
inline void lineLabelHigh(stringstream& buf, uInt16 addr)
|
||||||
{
|
{
|
||||||
if(!myDbg.getLabel(buf, addr, true))
|
stringstream buf8;
|
||||||
buf << "L" << Common::Base::HEX4 << addr;
|
|
||||||
|
buf8 << "'L";
|
||||||
|
if(myNumBanks > 1)
|
||||||
|
buf8 << Common::Base::HEX1 << myBank << "_";
|
||||||
|
buf8 << Common::Base::HEX4 << addr;
|
||||||
|
buf << std::left << std::setw(9) << std::setfill(' ') << buf8.str() << "'";
|
||||||
}
|
}
|
||||||
inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound)
|
|
||||||
|
inline void labelHigh(stringstream& buf, uInt16 addr)
|
||||||
|
{
|
||||||
|
if(!myDbg.getLabel(buf, myBank, addr, true))
|
||||||
|
{
|
||||||
|
buf << "L";
|
||||||
|
if(myNumBanks > 1)
|
||||||
|
buf << Common::Base::HEX1 << myBank << "_";
|
||||||
|
buf << Common::Base::HEX4 << addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void labelLow(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound)
|
||||||
{
|
{
|
||||||
myDbg.getLabel(buf, addr, ourLookup[op].rw_mode == RWMode::READ, 2);
|
myDbg.getLabel(buf, addr, ourLookup[op].rw_mode == RWMode::READ, 2);
|
||||||
if (labfound == AddressType::TIA)
|
if (labfound == AddressType::TIA)
|
||||||
|
@ -139,6 +160,8 @@ class DiStella
|
||||||
CartDebug::ReservedEquates& myReserved;
|
CartDebug::ReservedEquates& myReserved;
|
||||||
stringstream myDisasmBuf;
|
stringstream myDisasmBuf;
|
||||||
std::queue<uInt16> myAddressQueue;
|
std::queue<uInt16> myAddressQueue;
|
||||||
|
Int16 myBank{-1};
|
||||||
|
Int16 myNumBanks{1};
|
||||||
uInt16 myOffset{0}, myPC{0}, myPCEnd{0};
|
uInt16 myOffset{0}, myPC{0}, myPCEnd{0};
|
||||||
uInt16 mySegType{0};
|
uInt16 mySegType{0};
|
||||||
|
|
||||||
|
|
|
@ -317,7 +317,9 @@ int yylex() {
|
||||||
// happen if the user defines a label that matches one of
|
// happen if the user defines a label that matches one of
|
||||||
// the specials. Who would do that, though?
|
// the specials. Who would do that, though?
|
||||||
|
|
||||||
if(Debugger::debugger().cartDebug().getAddress(idbuf) > -1) {
|
CartDebug::BankAddress bankAddr = Debugger::debugger().cartDebug().getAddress(idbuf);
|
||||||
|
|
||||||
|
if(bankAddr.bank > -1) {
|
||||||
yylval.Equate = idbuf;
|
yylval.Equate = idbuf;
|
||||||
return EQUATE;
|
return EQUATE;
|
||||||
} else if( (cpuMeth = getCpuSpecial(idbuf)) ) {
|
} else if( (cpuMeth = getCpuSpecial(idbuf)) ) {
|
||||||
|
|
Loading…
Reference in New Issue