From 1ade2900e401f239b91d6387f53f3541cada35c6 Mon Sep 17 00:00:00 2001 From: stephena Date: Mon, 11 Mar 2013 19:43:19 +0000 Subject: [PATCH] More fixes to debugger disassembly for DASM. The code now prints out-of-range labels for cases where a label is in the middle of a multi-byte instruction (Kool Aid Man), and properly indicates mirrors of TIA read/write addresses (Meltdown). git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2666 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- Changes.txt | 16 +++++++++- src/debugger/CartDebug.cxx | 63 ++++++++++++++++++++++++++++---------- src/debugger/CartDebug.hxx | 9 +++--- src/debugger/DiStella.cxx | 40 ++++++++++++++++-------- 4 files changed, 95 insertions(+), 33 deletions(-) diff --git a/Changes.txt b/Changes.txt index 34b09e017..ed35d4670 100644 --- a/Changes.txt +++ b/Changes.txt @@ -14,7 +14,21 @@ 3.8.1 to 3.9: (XXXXX xx, 2013) - * Disassembly from debugger ... + * Greatly extended functionality of the debugger disassembly: + - The debugger now generates DASM-compatible disassembled code, + which can be saved to an external file. This disassembly is + based on both a static and runtime analysis, and is extremely + accurate. It also automatically differentiates between the + directives CODE/PGFX/GFX/DATA/ROW, whereas normal Distella + only differentiates between CODE and ROW. For now, only + single-bank (4K) ROMs are supported. + + - The disassembly now recognizes various TIA read/write mirrors, + and marks them as such (for example, INPT4.30 instead of INPT4 + for address $3C). + + - Fixed labelling in ROW directives; it wasn't accurately setting + a label in the case where it occurred in the middle of the data. * Fixed redundant "New console created" message when entering the same ROM multiple times from the ROM launcher. diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 08d1f52dd..fe891654c 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -36,7 +36,7 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem) : DebuggerSystem(dbg, console), myOSystem(osystem), myRWPortAddress(0), - myLabelLength(5) // longest pre-defined label + myLabelLength(8) // longest pre-defined label { // Zero-page RAM is always present addRamArea(0x80, 128, 0, 0); @@ -63,12 +63,12 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem) addLabel("START", myDebugger.dpeek(0xfffc)); // Add system equates - for(uInt16 addr = 0x00; addr <= 0x0F; ++addr) + for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) { mySystemAddresses.insert(make_pair(ourTIAMnemonicR[addr], addr)); myReserved.TIARead[addr] = false; } - for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) + for(uInt16 addr = 0x00; addr <= 0x7F; ++addr) { mySystemAddresses.insert(make_pair(ourTIAMnemonicW[addr], addr)); myReserved.TIAWrite[addr] = false; @@ -79,6 +79,8 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem) myReserved.IOReadWrite[addr-0x280] = false; } + myReserved.Label.clear(); + // Add settings for Distella DiStella::settings.gfx_format = myOSystem.settings().getInt("dis.gfxformat") == 16 ? kBASE_16 : kBASE_2; @@ -581,7 +583,7 @@ const string& CartDebug::getLabel(uInt16 addr, bool isRead, int places) const { case ADDR_TIA: return result = - (isRead ? ourTIAMnemonicR[addr&0x0f] : ourTIAMnemonicW[addr&0x3f]); + (isRead ? ourTIAMnemonicR[addr&0x3f] : ourTIAMnemonicW[addr&0x7f]); case ADDR_RIOT: { @@ -867,21 +869,25 @@ string CartDebug::saveDisassembly(string file) << "; P = PGFX directive, shown as '*' (stored in playfield)\n" << "\n processor 6502\n\n"; - for(uInt16 addr = 0x00; addr <= 0x0F; ++addr) + for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr][0] != '$') - buf << ALIGN(7) << ourTIAMnemonicR[addr] << " = $" + buf << ALIGN(10) << ourTIAMnemonicR[addr] << " = $" << HEX2 << right << addr << " ; (R)\n"; - for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) + for(uInt16 addr = 0x00; addr <= 0x7F; ++addr) if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr][0] != '$') - buf << ALIGN(7) << ourTIAMnemonicW[addr] << " = $" + buf << ALIGN(10) << ourTIAMnemonicW[addr] << " = $" << HEX2 << right << addr << " ; (W)\n"; for(uInt16 addr = 0x00; addr <= 0x17; ++addr) if(myReserved.IOReadWrite[addr] && ourIOMnemonic[addr][0] != '$') - buf << ALIGN(7) << ourIOMnemonic[addr] << " = $" + buf << ALIGN(10) << ourIOMnemonic[addr] << " = $" << HEX4 << right << (addr+0x280) << "\n"; + AddrToLabel::const_iterator iter; + for(iter = myReserved.Label.begin(); iter != myReserved.Label.end(); ++iter) + buf << ALIGN(10) << iter->second << " = $" << iter->first << "\n"; + buf << "\n"; // Use specific settings for disassembly output @@ -922,7 +928,7 @@ string CartDebug::saveDisassembly(string file) { case CartDebug::CODE: { - buf << ALIGN(16) << tag.disasm << tag.ccount << "\n"; + buf << ALIGN(19) << tag.disasm << tag.ccount << "\n"; break; } case CartDebug::NONE: @@ -1032,10 +1038,10 @@ string CartDebug::clearConfig(int bank) void CartDebug::getCompletions(const char* in, StringList& completions) const { // First scan system equates - for(uInt16 addr = 0x00; addr <= 0x0F; ++addr) + for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) if(BSPF_startsWithIgnoreCase(ourTIAMnemonicR[addr], in)) completions.push_back(ourTIAMnemonicR[addr]); - for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) + for(uInt16 addr = 0x00; addr <= 0x7F; ++addr) if(BSPF_startsWithIgnoreCase(ourTIAMnemonicW[addr], in)) completions.push_back(ourTIAMnemonicW[addr]); for(uInt16 addr = 0; addr <= 0x297-0x280; ++addr) @@ -1202,13 +1208,27 @@ void CartDebug::disasmTypeAsString(ostream& buf, uInt8 flags) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char* CartDebug::ourTIAMnemonicR[16] = { +const char* CartDebug::ourTIAMnemonicR[64] = { +// Standard $00-based TIA read locations: "CXM0P", "CXM1P", "CXP0FB", "CXP1FB", "CXM0FB", "CXM1FB", "CXBLPF", "CXPPMM", - "INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", "$0E", "$0F" + "INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", "$0E", "$0F", +// Mirrored $10-based TIA read locations: + "CXM0P.10", "CXM1P.10", "CXP0FB.10", "CXP1FB.10", "CXM0FB.10", "CXM1FB.10", + "CXBLPF.10", "CXPPMM.10", "INPT0.10", "INPT1.10", "INPT2.10", "INPT3.10", + "INPT4.10", "INPT5.10", "$1E", "$1F", +// Mirrored $20-based TIA read locations: + "CXM0P.20", "CXM1P.20", "CXP0FB.20", "CXP1FB.20", "CXM0FB.20", "CXM1FB.20", + "CXBLPF.20", "CXPPMM.20", "INPT0.20", "INPT1.20", "INPT2.20", "INPT3.20", + "INPT4.20", "INPT5.20", "$2E", "$2F", +// Mirrored $30-based TIA read locations: + "CXM0P.30", "CXM1P.30", "CXP0FB.30", "CXP1FB.30", "CXM0FB.30", "CXM1FB.30", + "CXBLPF.30", "CXPPMM.30", "INPT0.30", "INPT1.30", "INPT2.30", "INPT3.30", + "INPT4.30", "INPT5.30", "$3E", "$3F", }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char* CartDebug::ourTIAMnemonicW[64] = { +const char* CartDebug::ourTIAMnemonicW[128] = { +// Standard $00-based TIA write locations: "VSYNC", "VBLANK", "WSYNC", "RSYNC", "NUSIZ0", "NUSIZ1", "COLUP0", "COLUP1", "COLUPF", "COLUBK", "CTRLPF", "REFP0", "REFP1", "PF0", "PF1", "PF2", "RESP0", "RESP1", "RESM0", "RESM1", "RESBL", "AUDC0", "AUDC1", "AUDF0", @@ -1216,7 +1236,18 @@ const char* CartDebug::ourTIAMnemonicW[64] = { "HMP0", "HMP1", "HMM0", "HMM1", "HMBL", "VDELP0", "VDELP1", "VDELBL", "RESMP0", "RESMP1", "HMOVE", "HMCLR", "CXCLR", "$2D", "$2E", "$2F", "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", - "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F" + "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", +// Mirrored $40-based TIA write locations: + "VSYNC.40", "VBLANK.40", "WSYNC.40", "RSYNC.40", "NUSIZ0.40", "NUSIZ1.40", + "COLUP0.40", "COLUP1.40", "COLUPF.40", "COLUBK.40", "CTRLPF.40", "REFP0.40", + "REFP1.40", "PF0.40", "PF1.40", "PF2.40", "RESP0.40", "RESP1.40", "RESM0.40", + "RESM1.40", "RESBL.40", "AUDC0.40", "AUDC1.40", "AUDF0.40", "AUDF1.40", + "AUDV0.40", "AUDV1.40", "GRP0.40", "GRP1.40", "ENAM0.40", "ENAM1.40", + "ENABL.40", "HMP0.40", "HMP1.40", "HMM0.40", "HMM1.40", "HMBL.40", + "VDELP0.40", "VDELP1.40", "VDELBL.40", "RESMP0.40", "RESMP1.40", "HMOVE.40", + "HMCLR.40", "CXCLR.40", "$6D", "$6E", "$6F", + "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", + "$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F" }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 54ff6d859..33c5d05fc 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -291,9 +291,10 @@ class CartDebug : public DebuggerSystem // Information on equates used in the disassembly typedef struct { - bool TIARead[16]; - bool TIAWrite[64]; + bool TIARead[64]; + bool TIAWrite[128]; bool IOReadWrite[24]; + AddrToLabel Label; } ReservedEquates; ReservedEquates myReserved; @@ -347,8 +348,8 @@ class CartDebug : public DebuggerSystem uInt16 myLabelLength; /// Table of instruction mnemonics - static const char* ourTIAMnemonicR[16]; // read mode - static const char* ourTIAMnemonicW[64]; // write mode + static const char* ourTIAMnemonicR[64]; // read mode + static const char* ourTIAMnemonicW[128]; // write mode static const char* ourIOMnemonic[24]; }; diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index f7adf32e9..ca45984ff 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -184,6 +184,22 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, // Second pass disasm(myOffset, 2); + // Add reserved line equates + ostringstream reservedLabel; + for (int k = 0; k <= myAppData.end; k++) + { + if ((myLabels[k] & (CartDebug::REFERENCED | CartDebug::VALID_ENTRY)) == + CartDebug::REFERENCED) + { + // If we have a piece of code referenced somewhere else, but cannot + // locate the label in code (i.e because the address is inside of a + // multi-byte instruction, then we make note of that address for reference + reservedLabel.str(""); + reservedLabel << "L" << HEX4 << (k+myOffset); + myReserved.Label.insert(make_pair(k+myOffset, reservedLabel.str())); + } + } + // Third pass disasm(myOffset, 3); } @@ -526,13 +542,13 @@ void DiStella::disasm(uInt32 distart, int pass) { if(ourLookup[op].rw_mode == READ) { - nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x0f]; - myReserved.TIARead[d1&0x0f] = true; + nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x3f]; + myReserved.TIARead[d1&0x3f] = true; } else { - nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x3f]; - myReserved.TIAWrite[d1&0x3f] = true; + nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x7f]; + myReserved.TIAWrite[d1&0x7f] = true; } } else @@ -676,13 +692,13 @@ void DiStella::disasm(uInt32 distart, int pass) { if(ourLookup[op].rw_mode == READ) { - nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x0f] << ",X"; - myReserved.TIARead[d1&0x0f] = true; + nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x3f] << ",X"; + myReserved.TIARead[d1&0x3f] = true; } else { - nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x3f] << ",X"; - myReserved.TIAWrite[d1&0x3f] = true; + nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x7f] << ",X"; + myReserved.TIAWrite[d1&0x7f] = true; } } else @@ -702,13 +718,13 @@ void DiStella::disasm(uInt32 distart, int pass) { if(ourLookup[op].rw_mode == READ) { - nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x0f] << ",Y"; - myReserved.TIARead[d1&0x0f] = true; + nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x3f] << ",Y"; + myReserved.TIARead[d1&0x3f] = true; } else { - nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x3f] << ",Y"; - myReserved.TIAWrite[d1&0x3f] = true; + nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x7f] << ",Y"; + myReserved.TIAWrite[d1&0x7f] = true; } } else