mirror of https://github.com/stella-emu/stella.git
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:
parent
dac213c6c3
commit
bea8ac0ffd
|
@ -79,6 +79,7 @@ class CartDebug : public DebuggerSystem
|
|||
string disasm;
|
||||
string ccount;
|
||||
string bytes;
|
||||
bool hllabel;
|
||||
};
|
||||
typedef Common::Array<DisassemblyTag> DisassemblyList;
|
||||
typedef struct {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue