From 5d0b25cd48d3e5aac60628b7d6a4d47a37b8a36a Mon Sep 17 00:00:00 2001 From: stephena Date: Sat, 9 Oct 2010 17:55:22 +0000 Subject: [PATCH] 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 --- src/debugger/CartDebug.cxx | 13 ++-- src/debugger/CartDebug.hxx | 25 ++++--- src/debugger/DiStella.cxx | 109 ++++++++++++++++++----------- src/debugger/DiStella.hxx | 4 +- src/debugger/gui/RomListWidget.cxx | 4 +- 5 files changed, 96 insertions(+), 59 deletions(-) diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index aeeafc42c..c3d1b0e64 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -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; } } diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 2259d4517..72d212639 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -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; diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index 32b0fbb99..311a1d8bb 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -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); diff --git a/src/debugger/DiStella.hxx b/src/debugger/DiStella.hxx index 0d0a3c146..74b4155ca 100644 --- a/src/debugger/DiStella.hxx +++ b/src/debugger/DiStella.hxx @@ -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; diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 99a0c9613..1c1374799 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -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) {