mirror of https://github.com/stella-emu/stella.git
Enhance disassembly (determine correct bank offset, preliminary solution for simple 4K bankswitching, e.g. standard Atari)
This commit is contained in:
parent
32cd6e2a5b
commit
cae2266df0
|
@ -238,11 +238,51 @@ string CartDebug::toString()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::disassemble(bool force)
|
||||
{
|
||||
uInt16 PC = myDebugger.cpuDebug().pc();
|
||||
int bank = (PC & 0x1000) ? getBank(PC) : int(myBankInfo.size()) - 1;
|
||||
|
||||
return disassemble(bank, PC, force);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::disassembleBank(int bank)
|
||||
{
|
||||
// isolate the high 3 address bits, count them and
|
||||
// select the most frequent to define the bank offset
|
||||
BankInfo& info = myBankInfo[bank];
|
||||
uInt16 count[8];
|
||||
|
||||
for(int i = 0; i < 8; ++i)
|
||||
count[i] = 0;
|
||||
|
||||
for(uInt32 addr = 0x1000; addr < 0x1000 + info.size; ++addr)
|
||||
{
|
||||
Device::AccessFlags flags = mySystem.getAccessFlags(addr);
|
||||
// only count really accessed addresses
|
||||
if (flags & ~Device::ROW)
|
||||
count[(flags & Device::HADDR) >> 13]++;
|
||||
}
|
||||
uInt16 max = 0, maxIdx = 0;
|
||||
for(int idx = 0; idx < 8; ++idx)
|
||||
{
|
||||
if(count[idx] > max)
|
||||
{
|
||||
max = count[idx];
|
||||
maxIdx = idx;
|
||||
}
|
||||
}
|
||||
info.offset = maxIdx << 13 | 0x1000;
|
||||
|
||||
return disassemble(bank, info.offset, true);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::disassemble(int bank, uInt16 PC, bool force)
|
||||
{
|
||||
// Test current disassembly; don't re-disassemble if it hasn't changed
|
||||
// Also check if the current PC is in the current list
|
||||
bool bankChanged = myConsole.cartridge().bankChanged();
|
||||
uInt16 PC = myDebugger.cpuDebug().pc();
|
||||
int pcline = addressToLine(PC);
|
||||
bool pcfound = (pcline != -1) && (uInt32(pcline) < myDisassembly.list.size()) &&
|
||||
(myDisassembly.list[pcline].disasm[0] != '.');
|
||||
|
@ -254,8 +294,9 @@ bool CartDebug::disassemble(bool force)
|
|||
if(changed)
|
||||
{
|
||||
// Are we disassembling from ROM or ZP RAM?
|
||||
BankInfo& info = (PC & 0x1000) ? myBankInfo[getBank(PC)] :
|
||||
myBankInfo[myBankInfo.size()-1];
|
||||
BankInfo& info = myBankInfo[bank];
|
||||
//(PC & 0x1000) ? myBankInfo[getBank(PC)] :
|
||||
//myBankInfo[myBankInfo.size()-1];
|
||||
|
||||
// If the offset has changed, all old addresses must be 'converted'
|
||||
// For example, if the list contains any $fxxx and the address space is now
|
||||
|
@ -1044,6 +1085,7 @@ string CartDebug::saveDisassembly()
|
|||
|
||||
// prepare for switching banks
|
||||
myConsole.cartridge().unlockBank();
|
||||
uInt32 origin = 0;
|
||||
|
||||
for(int bank = 0; bank < bankCount; ++bank)
|
||||
{
|
||||
|
@ -1055,7 +1097,8 @@ string CartDebug::saveDisassembly()
|
|||
BankInfo& info = myBankInfo[bank];
|
||||
|
||||
// TODO: make PageAccess ready for multi-bank ROMs
|
||||
disassemble();
|
||||
// TODO: define offset if still undefined
|
||||
disassembleBank(bank);
|
||||
|
||||
// An empty address list means that DiStella can't do a disassembly
|
||||
if(info.addressList.size() == 0)
|
||||
|
@ -1081,8 +1124,9 @@ string CartDebug::saveDisassembly()
|
|||
if(bankCount == 1)
|
||||
buf << " ORG $" << Base::HEX4 << info.offset << "\n\n";
|
||||
else
|
||||
buf << " ORG $" << Base::HEX4 << ((0x0000 + bank * 0x1000) & 0xffff) << "\n"
|
||||
buf << " ORG $" << Base::HEX4 << origin << "\n"
|
||||
<< " RORG $" << Base::HEX4 << info.offset << "\n\n";
|
||||
origin += info.size;
|
||||
|
||||
// Format in 'distella' style
|
||||
for(uInt32 i = 0; i < disasm.list.size(); ++i)
|
||||
|
|
|
@ -94,23 +94,16 @@ class CartDebug : public DebuggerSystem
|
|||
// Return the base (= non-mirrored) address of the last CPU write
|
||||
int lastWriteBaseAddress();
|
||||
|
||||
// The following two methods are meant to be used together
|
||||
// First, a call is made to disassemble(), which updates the disassembly
|
||||
// list; it will figure out when an actual complete disassembly is
|
||||
// required, and when the previous results can be used
|
||||
//
|
||||
// Later, successive calls to disassemblyList() simply return the
|
||||
// previous results; no disassembly is done in this case
|
||||
/**
|
||||
Disassemble from the given address using the Distella disassembler
|
||||
Address-to-label mappings (and vice-versa) are also determined here
|
||||
|
||||
@param force Force a re-disassembly, even if the state hasn't changed
|
||||
|
||||
@return True if disassembly changed from previous call, else false
|
||||
*/
|
||||
// TODO
|
||||
bool disassemble(bool force = false);
|
||||
bool disassembleBank(int bank);
|
||||
|
||||
// First, a call is made to disassemble(), which updates the disassembly
|
||||
// list, is required; it will figure out when an actual complete
|
||||
// disassembly is required, and when the previous results can be used
|
||||
//
|
||||
// Later, successive calls to disassembly() simply return the
|
||||
// previous results; no disassembly is done in this case
|
||||
/**
|
||||
Get the results from the most recent call to disassemble()
|
||||
*/
|
||||
|
@ -278,6 +271,19 @@ class CartDebug : public DebuggerSystem
|
|||
};
|
||||
ReservedEquates myReserved;
|
||||
|
||||
/**
|
||||
Disassemble from the given address using the Distella disassembler
|
||||
Address-to-label mappings (and vice-versa) are also determined here
|
||||
|
||||
@param bank The current bank to disassemble
|
||||
@param PC A program counter to start with
|
||||
@param force Force a re-disassembly, even if the state hasn't changed
|
||||
|
||||
@return True if disassembly changed from previous call, else false
|
||||
*/
|
||||
bool disassemble(int bank, uInt16 PC, bool force = false);
|
||||
|
||||
|
||||
// Actually call DiStella to fill the DisassemblyList structure
|
||||
// Return whether the search address was actually in the list
|
||||
bool fillDisassemblyList(BankInfo& bankinfo, uInt16 search);
|
||||
|
|
|
@ -969,9 +969,9 @@ bool DiStella::checkBit(uInt16 address, uInt16 mask, bool useDebugger) const
|
|||
// Since they're set only in the labels array (as the lower two bits),
|
||||
// they must be included in the other bitfields
|
||||
uInt16 label = myLabels[address & myAppData.end],
|
||||
lastbits = label & 0x03,
|
||||
directive = myDirectives[address & myAppData.end] & ~0x03,
|
||||
debugger = Debugger::debugger().getAccessFlags(address | myOffset) & ~0x03;
|
||||
lastbits = label & (Device::REFERENCED | Device::VALID_ENTRY),
|
||||
directive = myDirectives[address & myAppData.end] & ~(Device::REFERENCED | Device::VALID_ENTRY),
|
||||
debugger = Debugger::debugger().getAccessFlags(address | myOffset) & ~(Device::REFERENCED | Device::VALID_ENTRY);
|
||||
|
||||
// Any address marked by a manual directive always takes priority
|
||||
if (directive)
|
||||
|
|
|
@ -44,18 +44,20 @@ class Device : public Serializable
|
|||
|
||||
// The following correspond to specific types that can be set within the
|
||||
// debugger, or specified in a Distella cfg file, and are listed in order
|
||||
// of decreasing hierarchy
|
||||
// of increasing hierarchy
|
||||
//
|
||||
CODE = 1 << 11, // 0x800, disassemble-able code segments
|
||||
TCODE = 1 << 10, // 0x400, (tentative) disassemble-able code segments
|
||||
GFX = 1 << 9, // 0x200, addresses loaded into GRPx registers
|
||||
PGFX = 1 << 8, // 0x100, addresses loaded into PFx registers
|
||||
COL = 1 << 7, // 0x080, addresses loaded into COLUPx registers
|
||||
PCOL = 1 << 6, // 0x040, addresses loaded into COLUPF register
|
||||
BCOL = 1 << 5, // 0x020, addresses loaded into COLUBK register
|
||||
AUD = 1 << 4, // 0x010, addresses loaded into audio registers
|
||||
DATA = 1 << 3, // 0x008, addresses loaded into registers other than GRPx / PFx / COLUxx, AUDxx
|
||||
ROW = 1 << 2, // 0x004, all other addresses
|
||||
DATA = 1 << 3, // 0x008, addresses loaded into registers other than GRPx / PFx / COLUxx, AUDxx
|
||||
AUD = 1 << 4, // 0x010, addresses loaded into audio registers
|
||||
BCOL = 1 << 5, // 0x020, addresses loaded into COLUBK register
|
||||
PCOL = 1 << 6, // 0x040, addresses loaded into COLUPF register
|
||||
COL = 1 << 7, // 0x080, addresses loaded into COLUPx registers
|
||||
PGFX = 1 << 8, // 0x100, addresses loaded into PFx registers
|
||||
GFX = 1 << 9, // 0x200, addresses loaded into GRPx registers
|
||||
TCODE = 1 << 10, // 0x400, (tentative) disassemble-able code segments
|
||||
CODE = 1 << 11, // 0x800, disassemble-able code segments
|
||||
// special bits for address
|
||||
HADDR = 1 << 13 | 1 << 14 | 1 << 15, // 0xe000, // highest 3 address bits
|
||||
// special type for poke()
|
||||
WRITE = TCODE // 0x200, address written to
|
||||
};
|
||||
|
|
|
@ -106,7 +106,7 @@ uInt8 System::peek(uInt16 addr, Device::AccessFlags flags)
|
|||
#ifdef DEBUGGER_SUPPORT
|
||||
// Set access type
|
||||
if(access.romAccessBase)
|
||||
*(access.romAccessBase + (addr & PAGE_MASK)) |= flags;
|
||||
*(access.romAccessBase + (addr & PAGE_MASK)) |= (flags | (addr & Device::HADDR));
|
||||
else
|
||||
access.device->setAccessFlags(addr, flags);
|
||||
#endif
|
||||
|
@ -134,8 +134,8 @@ void System::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags)
|
|||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
// Set access type
|
||||
if (access.romAccessBase)
|
||||
*(access.romAccessBase + (addr & PAGE_MASK)) |= flags;
|
||||
if(access.romAccessBase)
|
||||
*(access.romAccessBase + (addr & PAGE_MASK)) |= (flags | (addr & Device::HADDR));
|
||||
else
|
||||
access.device->setAccessFlags(addr, flags);
|
||||
#endif
|
||||
|
@ -177,7 +177,7 @@ void System::setAccessFlags(uInt16 addr, Device::AccessFlags flags)
|
|||
const PageAccess& access = getPageAccess(addr);
|
||||
|
||||
if(access.romAccessBase)
|
||||
*(access.romAccessBase + (addr & PAGE_MASK)) |= flags;
|
||||
*(access.romAccessBase + (addr & PAGE_MASK)) |= (flags | (addr & Device::HADDR));
|
||||
else
|
||||
access.device->setAccessFlags(addr, flags);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue