Properly implemented an hierarchy wrt marking an address in the disassembly

in a consistent way.  Directives set manually have top priority, then the
results from a dynamic analysis (aka, from actually running the code), and
finally from a static analysis (aka, Distella itself).

Sometimes Distella will mark a section as CODE even if it hasn't been
marked as such dynamically.  This occurs after a relative branch, which
Distella has no idea how to evaluate.  It's possible that the code will
be executed eventually, but also that it will never be executed.  As such,
these lines are marked with a '*', indicating that disassembly results
are tentative.  If you get weird looking disassembly for these addresses,
it's probably a hint that it isn't really code at all.

PC addresses in the disassembly labels are now aligned with labels, and
shown in a lighter color.  These can still be toggled on and off.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2162 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-10-23 20:57:31 +00:00
parent dac213c6c3
commit bea8ac0ffd
5 changed files with 46 additions and 25 deletions

View File

@ -79,6 +79,7 @@ class CartDebug : public DebuggerSystem
string disasm;
string ccount;
string bytes;
bool hllabel;
};
typedef Common::Array<DisassemblyTag> DisassemblyList;
typedef struct {

View File

@ -83,6 +83,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
info.offset = myOffset;
memset(labels, 0, 0x1000);
memset(directives, 0, 0x1000);
myAddressQueue.push(start);
// Process any directives first, as they override automatic code determination
@ -126,7 +127,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
uInt16 addr = *it;
if(!check_bit(addr-myOffset, CartDebug::CODE))
{
cerr << "(list) marking " << HEX4 << addr << " as CODE\n";
//cerr << "(list) marking " << HEX4 << addr << " as CODE\n";
myAddressQueue.push(addr);
++it;
break;
@ -142,7 +143,7 @@ cerr << "(list) marking " << HEX4 << addr << " as CODE\n";
if((Debugger::debugger().getAddressDisasmType(codeAccessPoint+myOffset) & CartDebug::CODE)
&& !(labels[codeAccessPoint & myAppData.end] & CartDebug::CODE))
{
cerr << "(emul) marking " << HEX4 << (codeAccessPoint+myOffset) << " as CODE\n";
//cerr << "(emul) marking " << HEX4 << (codeAccessPoint+myOffset) << " as CODE\n";
myAddressQueue.push(codeAccessPoint+myOffset);
++codeAccessPoint;
break;
@ -729,7 +730,7 @@ void DiStella::disasm(uInt32 distart, int pass)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int DiStella::mark(uInt32 address, uInt8 mask)
int DiStella::mark(uInt32 address, uInt8 mask, bool directive)
{
/*-----------------------------------------------------------------------
For any given offset and code range...
@ -780,8 +781,8 @@ int DiStella::mark(uInt32 address, uInt8 mask)
if (address >= myOffset && address <= myAppData.end + myOffset)
{
// Debugger::debugger().setAddressDisasmType(address | myOffset, mask);
labels[address-myOffset] = labels[address-myOffset] | mask;
if(directive) directives[address-myOffset] = mask;
return 1;
}
else if (address >= 0 && address <= 0x3f)
@ -795,8 +796,8 @@ int DiStella::mark(uInt32 address, uInt8 mask)
else if (address > 0x1000)
{
/* 2K & 4K case */
// Debugger::debugger().setAddressDisasmType(address | myOffset, mask);
labels[address & myAppData.end] = labels[address & myAppData.end] | mask;
if(directive) directives[address & myAppData.end] = mask;
return 4;
}
else
@ -806,10 +807,24 @@ int DiStella::mark(uInt32 address, uInt8 mask)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DiStella::check_bit(uInt16 address, uInt8 mask) const
{
if(Debugger::debugger().getAddressDisasmType(address | myOffset) & mask)
// The REFERENCED and VALID_ENTRY flags are needed for any inspection of
// an address
// Since they're set only in the labels array (as the lower two bits),
// they must be included in the other bitfields
uInt8 label = labels[address & myAppData.end],
lastbits = label & 0x03,
directive = directives[address & myAppData.end] & 0xFC,
debugger = Debugger::debugger().getAddressDisasmType(address | myOffset) & 0xFC;
// Any address marked by a manual directive always takes priority
if(directive)
return (directive | lastbits) & mask;
// Next, the results from a dynamic/runtime analysis are used
else if((debugger | lastbits) & mask)
return true;
// Otherwise, default to static analysis from Distella
else
return labels[address & myAppData.end] & mask;
return label & mask;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -860,6 +875,7 @@ void DiStella::addEntry(CartDebug::DisasmType type)
if(tag.address)
{
tag.label = myDbg.getLabel(tag.address, true);
tag.hllabel = true;
if(tag.label == EmptyString)
{
if(myDisasmBuf.peek() != ' ')
@ -868,8 +884,9 @@ void DiStella::addEntry(CartDebug::DisasmType type)
{
// Have addresses indented, to differentiate from actual labels
char address[8];
sprintf(address, " $%X", tag.address);
sprintf(address, " %X", tag.address);
tag.label = address;
tag.hllabel = false;
}
}
}
@ -887,6 +904,14 @@ void DiStella::addEntry(CartDebug::DisasmType type)
getline(myDisasmBuf, tag.disasm, '\'');
getline(myDisasmBuf, tag.ccount, '\'');
getline(myDisasmBuf, tag.bytes);
// Make note of when we override CODE sections from the debugger
// It could mean that the code hasn't been accessed up to this point,
// but it could also indicate that code will *never* be accessed
// Since it is impossible to tell the difference, marking the address
// in the disassembly at least tells the user about it
if(!(Debugger::debugger().getAddressDisasmType(tag.address) & CartDebug::CODE))
tag.ccount += " *";
break;
case CartDebug::GFX:
case CartDebug::PGFX:
@ -909,15 +934,6 @@ void DiStella::addEntry(CartDebug::DisasmType type)
DONE_WITH_ADD:
myDisasmBuf.clear();
myDisasmBuf.str("");
#if 0
// debugging output
cerr << (tag.type == CartDebug::CODE ? "CartDebug::CODE" : (tag.type == CartDebug::ROW ? "CartDebug::ROW" :
(tag.type == CartDebug::GFX ? "CartDebug::GFX " : "NONE"))) << "|"
<< hex << setw(4) << setfill('0') << tag.address << "|"
<< tag.label << "|" << tag.disasm << "|" << tag.ccount << "|" << "|"
<< tag.bytes << endl;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -929,7 +945,7 @@ void DiStella::processDirectives(const CartDebug::DirectiveList& directives)
const CartDebug::DirectiveTag tag = *i;
if(check_range(tag.start, tag.end))
for(uInt32 k = tag.start; k <= tag.end; ++k)
mark(k, tag.type);
mark(k, tag.type, true);
}
}

View File

@ -84,7 +84,7 @@ class DiStella
// These functions are part of the original Distella code
void disasm(uInt32 distart, int pass);
bool check_range(uInt16 start, uInt16 end) const;
int mark(uInt32 address, uInt8 mask);
int mark(uInt32 address, uInt8 mask, bool directive = false);
bool check_bit(uInt16 address, uInt8 mask) const;
private:
@ -100,8 +100,11 @@ class DiStella
uInt16 length;
} myAppData;
/* Stores info on how each address is marked */
uInt8 labels[0x1000];
/* Stores info on how each address is marked, both in the general
case as well as when manual directives are enabled (in which case
the directives take priority
The address mark type is defined in CartDebug.hxx */
uInt8 labels[0x1000], directives[0x1000];
/**
Enumeration of the 6502 addressing modes

View File

@ -446,7 +446,7 @@ void RomListWidget::drawWidget(bool hilite)
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
// Draw the list items
int ccountw = _fontWidth << 1,
int ccountw = _fontWidth << 2,
large_disasmw = _w - l.x() - _labelWidth,
medium_disasmw = large_disasmw - r.width(),
small_disasmw = medium_disasmw - (ccountw << 1),
@ -476,11 +476,12 @@ void RomListWidget::drawWidget(bool hilite)
}
// Draw labels
s.drawString(_font, dlist[pos].label, xpos, ypos, _labelWidth, kTextColor);
s.drawString(_font, dlist[pos].label, xpos, ypos, _labelWidth,
dlist[pos].hllabel ? kTextColor : kColor);
// Bytes are only editable if they represent code, graphics, or accessible data
// Otherwise, the disassembly should get all remaining space
if(dlist[pos].type & (CartDebug::CODE | CartDebug::GFX | CartDebug::DATA))
if(dlist[pos].type & (CartDebug::CODE|CartDebug::GFX|CartDebug::PGFX|CartDebug::DATA))
{
if(dlist[pos].type == CartDebug::CODE)
{

View File

@ -302,7 +302,7 @@ void Cartridge::createCodeAccessBase(uInt32 size)
{
#ifdef DEBUGGER_SUPPORT
myCodeAccessBase = new uInt8[size];
memset(myCodeAccessBase, 0, size);
memset(myCodeAccessBase, CartDebug::ROW, size);
#else
myCodeAccessBase = NULL;
#endif