Re-added 'REFERENCED' type to Distella, instead of always using 'DATA'. I just

realized that not all things that are referenced are actually data; code can be
referenced too.

Implemented handling of 'DATA' directive.  This is very similar to 'GFX',
except X's are not shown for the bits, and the disassembled bytes are always
in hex.  For now, it can only be activated manually with a cfg command.
Its real value will become apparent once the emulation tracks when
addresses are actually accessed, differentiating from addresses that are
never referenced (ie, 'ROW').  This will fix the current deficiency in 
modifying DATA values (it can't be done, since they're packed into 16 bytes per
line and not changable).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2144 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-10-09 17:55:22 +00:00
parent fa3dc7cc38
commit 5d0b25cd48
5 changed files with 96 additions and 59 deletions

View File

@ -352,10 +352,14 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const
bool CartDebug::addDirective(CartDebug::DisasmType type,
uInt16 start, uInt16 end, int bank)
{
#define PRINT_TAG(tag) \
disasmTypeAsString(cerr, tag.type); \
cerr << ": start = " << tag.start << ", end = " << tag.end << endl;
#define PRINT_LIST(header) \
cerr << header << endl; \
for(DirectiveList::const_iterator d = list.begin(); d != list.end(); ++d) \
PRINT_TAG((*d)); \
for(DirectiveList::const_iterator d = list.begin(); d != list.end(); ++d) { \
PRINT_TAG((*d)); } \
cerr << endl;
if(end < start || start == 0 || end == 0)
@ -396,7 +400,7 @@ bool CartDebug::addDirective(CartDebug::DisasmType type,
// Case 1: remove range that is completely inside new range
if(tag.start <= i->start && tag.end >= i->end)
{
list.erase(i);
i = list.erase(i);
}
// Case 2: split the old range
else if(tag.start >= i->start && tag.end <= i->end)
@ -1000,13 +1004,12 @@ void CartDebug::disasmTypeAsString(ostream& buf, DisasmType type) const
{
switch(type)
{
case CartDebug::NONE: buf << "NONE"; break;
case CartDebug::VALID: buf << "VALID"; break;
case CartDebug::SKIP: buf << "SKIP"; break;
case CartDebug::CODE: buf << "CODE"; break;
case CartDebug::GFX: buf << "GFX"; break;
case CartDebug::DATA: buf << "DATA"; break;
case CartDebug::ROW: buf << "ROW"; break;
default: break;
}
}

View File

@ -54,15 +54,22 @@ class CartDebug : public DebuggerSystem
public:
enum DisasmType {
NONE = 0,
VALID = 1 << 0, /* addresses that can have a label placed in front of it. A good counterexample
would be "FF00: LDA $FE00"; $FF01 would be in the middle of a multi-byte
instruction, and therefore cannot be labelled. */
SKIP = 1 << 1, /* TODO - document this */
CODE = 1 << 2, /* disassemble-able code segments */
GFX = 1 << 3, /* addresses loaded into GRPx registers */
DATA = 1 << 4, /* code somewhere in the program references it, i.e. LDA $F372 referenced $F372 */
ROW = 1 << 5 /* all other addresses */
NONE = 0,
VALID_ENTRY = 1 << 0, /* addresses that can have a label placed in front of it.
A good counterexample would be "FF00: LDA $FE00"; $FF01
would be in the middle of a multi-byte instruction, and
therefore cannot be labelled. */
REFERENCED = 1 << 1, /* code somewhere in the program references it,
i.e. LDA $F372 referenced $F372 */
// The following correspond to specific types that can be set within the
// debugger, or specified in a Distella cfg file
//
SKIP = 1 << 2, // TODO - document this
CODE = 1 << 3, // disassemble-able code segments
GFX = 1 << 4, // addresses loaded into GRPx registers
DATA = 1 << 5, // addresses loaded into registers other than GRPx
ROW = 1 << 6 // all other addresses
};
struct DisassemblyTag {
DisasmType type;

View File

@ -123,7 +123,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
while(it != addresses.end())
{
uInt16 addr = *it;
if(!check_bit(labels[addr-myOffset], CartDebug::CODE))
if(!check_bit(addr-myOffset, CartDebug::CODE))
{
cerr << "(list) marking " << HEX4 << addr << " as CODE\n";
myAddressQueue.push(addr);
@ -135,11 +135,11 @@ cerr << "(list) marking " << HEX4 << addr << " as CODE\n";
}
// Stella itself can provide hints on whether an address has ever
// been referenced as CartDebug::CODE
// been referenced as CODE
while(it == addresses.end() && codeAccessPoint <= myAppData.end)
{
if(Debugger::debugger().isCode(codeAccessPoint+myOffset) &&
!check_bit(labels[codeAccessPoint], CartDebug::CODE))
!check_bit(codeAccessPoint, CartDebug::CODE))
{
cerr << "(emul) marking " << HEX4 << (codeAccessPoint+myOffset) << " as CODE\n";
myAddressQueue.push(codeAccessPoint+myOffset);
@ -153,7 +153,7 @@ cerr << "(emul) marking " << HEX4 << (codeAccessPoint+myOffset) << " as CODE\n";
for (int k = 0; k <= myAppData.end; k++)
{
if (!check_bit(labels[k], CartDebug::CODE))
if (!check_bit(k, CartDebug::CODE))
mark(k+myOffset, CartDebug::ROW);
}
}
@ -189,14 +189,14 @@ void DiStella::disasm(uInt32 distart, int pass)
myPC = distart - myOffset;
while(myPC <= myAppData.end)
{
if(check_bit(labels[myPC], CartDebug::GFX))
/* && !check_bit(labels[myPC], CartDebug::CODE))*/
if(check_bit(myPC, CartDebug::GFX))
/* && !check_bit(myPC, CartDebug::CODE))*/
{
if (pass == 2)
mark(myPC+myOffset, CartDebug::VALID);
mark(myPC+myOffset, CartDebug::VALID_ENTRY);
else if (pass == 3)
{
if (check_bit(labels[myPC], CartDebug::DATA))
if (check_bit(myPC, CartDebug::REFERENCED))
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'";
else
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
@ -214,10 +214,31 @@ void DiStella::disasm(uInt32 distart, int pass)
}
myPC++;
}
else if (check_bit(labels[myPC], CartDebug::ROW) && !check_bit(labels[myPC], CartDebug::GFX))
/* && !check_bit(labels[myPC], CartDebug::CODE)) { */
else if (check_bit(myPC, CartDebug::DATA) &&
!check_bit(myPC, CartDebug::CODE|CartDebug::GFX))
{
mark(myPC+myOffset, CartDebug::VALID);
if (pass == 2)
mark(myPC+myOffset, CartDebug::VALID_ENTRY);
else if (pass == 3)
{
if (check_bit(myPC, CartDebug::REFERENCED))
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'";
else
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
uInt8 byte = Debugger::debugger().peek(myPC+myOffset);
myDisasmBuf << ".byte $" << HEX2 << (int)byte << " $"
<< HEX4 << myPC+myOffset << "'"
<< HEX2 << (int)byte;
cerr << myDisasmBuf.str() << endl;
addEntry(CartDebug::DATA);
}
myPC++;
}
else if (check_bit(myPC, CartDebug::ROW) && !check_bit(myPC, CartDebug::GFX))
/* && !check_bit(myPC, CartDebug::CODE)) { */
{
mark(myPC+myOffset, CartDebug::VALID_ENTRY);
if (pass == 3)
{
bytes = 1;
@ -226,21 +247,20 @@ void DiStella::disasm(uInt32 distart, int pass)
}
myPC++;
while (check_bit(labels[myPC], CartDebug::ROW) && !check_bit(labels[myPC], CartDebug::DATA)
&& !check_bit(labels[myPC], CartDebug::GFX) && pass == 3 && myPC <= myAppData.end)
while (check_bit(myPC, CartDebug::ROW) &&
!check_bit(myPC, CartDebug::REFERENCED|CartDebug::DATA|CartDebug::GFX)
&& pass == 3 && myPC <= myAppData.end)
{
if (pass == 3)
bytes++;
if (bytes == 17)
{
bytes++;
if (bytes == 17)
{
addEntry(CartDebug::ROW);
myDisasmBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
bytes = 1;
}
else
myDisasmBuf << ",$" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
addEntry(CartDebug::ROW);
myDisasmBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
bytes = 1;
}
else
myDisasmBuf << ",$" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
myPC++;
}
@ -256,10 +276,10 @@ void DiStella::disasm(uInt32 distart, int pass)
op = Debugger::debugger().peek(myPC+myOffset);
/* version 2.1 bug fix */
if (pass == 2)
mark(myPC+myOffset, CartDebug::VALID);
mark(myPC+myOffset, CartDebug::VALID_ENTRY);
else if (pass == 3)
{
if (check_bit(labels[myPC], CartDebug::DATA))
if (check_bit(myPC, CartDebug::REFERENCED))
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'";
else
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
@ -312,7 +332,7 @@ void DiStella::disasm(uInt32 distart, int pass)
if (myPC == myAppData.end)
{
if (check_bit(labels[myPC], CartDebug::DATA))
if (check_bit(myPC, CartDebug::REFERENCED))
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'";
else
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
@ -376,10 +396,10 @@ void DiStella::disasm(uInt32 distart, int pass)
case ABSOLUTE:
{
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, CartDebug::DATA);
labfound = mark(ad, CartDebug::REFERENCED);
if (pass == 1)
{
if ((addbranch) && !check_bit(labels[ad & myAppData.end], CartDebug::CODE))
if ((addbranch) && !check_bit(ad & myAppData.end, CartDebug::CODE))
{
if (ad > 0xfff)
myAddressQueue.push((ad & myAppData.end) + myOffset);
@ -422,7 +442,7 @@ void DiStella::disasm(uInt32 distart, int pass)
case ZERO_PAGE:
{
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
labfound = mark(d1, CartDebug::DATA);
labfound = mark(d1, CartDebug::REFERENCED);
if (pass == 3)
{
if (labfound == 2)
@ -450,7 +470,7 @@ void DiStella::disasm(uInt32 distart, int pass)
case ABSOLUTE_X:
{
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, CartDebug::DATA);
labfound = mark(ad, CartDebug::REFERENCED);
if (pass == 3)
{
if (ad < 0x100)
@ -486,7 +506,7 @@ void DiStella::disasm(uInt32 distart, int pass)
case ABSOLUTE_Y:
{
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, CartDebug::DATA);
labfound = mark(ad, CartDebug::REFERENCED);
if (pass == 3)
{
if (ad < 0x100)
@ -544,7 +564,7 @@ void DiStella::disasm(uInt32 distart, int pass)
case ZERO_PAGE_X:
{
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
labfound = mark(d1, CartDebug::DATA);
labfound = mark(d1, CartDebug::REFERENCED);
if (pass == 3)
{
if (labfound == 2)
@ -561,7 +581,7 @@ void DiStella::disasm(uInt32 distart, int pass)
case ZERO_PAGE_Y:
{
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
labfound = mark(d1, CartDebug::DATA);
labfound = mark(d1, CartDebug::REFERENCED);
if (pass == 3)
{
if (labfound == 2)
@ -583,10 +603,10 @@ void DiStella::disasm(uInt32 distart, int pass)
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
ad = ((myPC + (Int8)d1) & 0xfff) + myOffset;
labfound = mark(ad, CartDebug::DATA);
labfound = mark(ad, CartDebug::REFERENCED);
if (pass == 1)
{
if ((addbranch) && !check_bit(labels[ad-myOffset], CartDebug::CODE))
if ((addbranch) && !check_bit(ad-myOffset, CartDebug::CODE))
{
myAddressQueue.push(ad);
mark(ad, CartDebug::CODE);
@ -609,7 +629,7 @@ void DiStella::disasm(uInt32 distart, int pass)
case ABS_INDIRECT:
{
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, CartDebug::DATA);
labfound = mark(ad, CartDebug::REFERENCED);
if (pass == 3)
{
if (ad < 0x100)
@ -666,7 +686,7 @@ void DiStella::disasm(uInt32 distart, int pass)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int DiStella::mark(uInt16 address, uInt8 bit)
int DiStella::mark(uInt16 address, uInt8 mask)
{
/*-----------------------------------------------------------------------
For any given offset and code range...
@ -717,7 +737,7 @@ int DiStella::mark(uInt16 address, uInt8 bit)
if (address >= myOffset && address <= myAppData.end + myOffset)
{
labels[address-myOffset] = labels[address-myOffset] | bit;
labels[address-myOffset] = labels[address-myOffset] | mask;
return 1;
}
else if (address >= 0 && address <= 0x3f)
@ -731,13 +751,19 @@ int DiStella::mark(uInt16 address, uInt8 bit)
else if (address > 0x1000)
{
/* 2K & 4K case */
labels[address & myAppData.end] = labels[address & myAppData.end] | bit;
labels[address & myAppData.end] = labels[address & myAppData.end] | mask;
return 4;
}
else
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DiStella::check_bit(uInt16 address, uInt8 mask) const
{
return (labels[address] & mask) == mask;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DiStella::check_range(uInt16 beg, uInt16 end) const
{
@ -818,8 +844,9 @@ void DiStella::addEntry(CartDebug::DisasmType type)
getline(myDisasmBuf, tag.disasm, '\'');
getline(myDisasmBuf, tag.bytes);
break;
case CartDebug::DATA: // TODO - handle this
tag.disasm = " ";
case CartDebug::DATA:
getline(myDisasmBuf, tag.disasm, '\'');
getline(myDisasmBuf, tag.bytes);
break;
case CartDebug::ROW:
getline(myDisasmBuf, tag.disasm);

View File

@ -83,9 +83,9 @@ class DiStella
// These functions are part of the original Distella code
void disasm(uInt32 distart, int pass);
int mark(uInt16 address, uInt8 bit);
bool check_range(uInt16 start, uInt16 end) const;
inline uInt8 check_bit(uInt8 bitflags, uInt8 i) const { return (bitflags & i); }
int mark(uInt16 address, uInt8 mask);
bool check_bit(uInt16 address, uInt8 mask) const;
private:
const CartDebug& myDbg;

View File

@ -477,9 +477,9 @@ void RomListWidget::drawWidget(bool hilite)
// Draw labels
s.drawString(_font, dlist[pos].label, xpos, ypos, _labelWidth, kTextColor);
// Bytes are only editable if they represent code or graphics
// 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))
if(dlist[pos].type & (CartDebug::CODE | CartDebug::GFX | CartDebug::DATA))
{
if(dlist[pos].type == CartDebug::CODE)
{