Further improvements to the DiStella class. The output is now properly

parsed into a DisassemblyList structure.  For now, this is just being
printed out again.  The next change will be to pass this to RomWidget
and have it displayed in the UI.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1929 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-01-31 19:41:57 +00:00
parent 231958dbdf
commit 898d16b863
2 changed files with 68 additions and 53 deletions

View File

@ -37,7 +37,8 @@ DiStella::~DiStella()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 DiStella::disassemble(DisassemblyList& list, const char* datafile, bool autocode) uInt32 DiStella::disassemble(DisassemblyList& list, uInt16 PC,
const char* datafile, bool autocode)
{ {
myLineCount = 0; myLineCount = 0;
while(!myAddressQueue.empty()) while(!myAddressQueue.empty())
@ -78,7 +79,7 @@ uInt32 DiStella::disassemble(DisassemblyList& list, const char* datafile, bool a
Counter 3 bytes back from the final byte. Counter 3 bytes back from the final byte.
-----------------------------------------------------*/ -----------------------------------------------------*/
myPC = myAppData.end - 3; myPC = PC;
uInt32 start_adr = read_adr(); uInt32 start_adr = read_adr();
if (myAppData.end == 0x7ff) /* 2K case */ if (myAppData.end == 0x7ff) /* 2K case */
@ -134,8 +135,8 @@ uInt32 DiStella::disassemble(DisassemblyList& list, const char* datafile, bool a
myPC = myAddressQueue.front(); myPC = myAddressQueue.front();
myPCBeg = myPC; myPCBeg = myPC;
myAddressQueue.pop(); myAddressQueue.pop();
disasm(myPC, 1); disasm(list, myPC, 1);
for (int k = myPCBeg; k <= myPCEnd; k++) for (uInt32 k = myPCBeg; k <= myPCEnd; k++)
mark(k, REACHABLE); mark(k, REACHABLE);
} }
@ -147,10 +148,10 @@ uInt32 DiStella::disassemble(DisassemblyList& list, const char* datafile, bool a
} }
// Second pass // Second pass
disasm(myOffset, 2); disasm(list, myOffset, 2);
// Third pass // Third pass
disasm(myOffset, 3); disasm(list, myOffset, 3);
free(labels); /* Free dynamic memory before program ends */ free(labels); /* Free dynamic memory before program ends */
free(mem); /* Free dynamic memory before program ends */ free(mem); /* Free dynamic memory before program ends */
@ -228,7 +229,7 @@ int DiStella::file_load(const char* file)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DiStella::disasm(uInt32 distart, int pass) void DiStella::disasm(DisassemblyList& list, uInt32 distart, int pass)
{ {
#define HEX4 uppercase << hex << setw(4) << setfill('0') #define HEX4 uppercase << hex << setw(4) << setfill('0')
#define HEX2 uppercase << hex << setw(2) << setfill('0') #define HEX2 uppercase << hex << setw(2) << setfill('0')
@ -236,7 +237,7 @@ void DiStella::disasm(uInt32 distart, int pass)
uInt8 op, d1, opsrc; uInt8 op, d1, opsrc;
uInt32 ad; uInt32 ad;
short amode; short amode;
int i, bytes, labfound, addbranch; int bytes=0, labfound=0, addbranch=0;
char linebuff[256],nextline[256], nextlinebytes[256]; char linebuff[256],nextline[256], nextlinebytes[256];
strcpy(linebuff,""); strcpy(linebuff,"");
strcpy(nextline,""); strcpy(nextline,"");
@ -245,7 +246,6 @@ void DiStella::disasm(uInt32 distart, int pass)
/* pc=myAppData.start; */ /* pc=myAppData.start; */
myPC = distart - myOffset; myPC = distart - myOffset;
//cerr << " ==> pc = " << pc << "(" << pass << ")" << endl;
while(myPC <= myAppData.end) while(myPC <= myAppData.end)
{ {
if(check_bit(labels[myPC], GFX)) if(check_bit(labels[myPC], GFX))
@ -263,7 +263,7 @@ void DiStella::disasm(uInt32 distart, int pass)
myBuf << ".byte $" << HEX2 << (int)mem[myPC] << " ; "; myBuf << ".byte $" << HEX2 << (int)mem[myPC] << " ; ";
showgfx(mem[myPC]); showgfx(mem[myPC]);
myBuf << " $" << HEX4 << myPC+myOffset; myBuf << " $" << HEX4 << myPC+myOffset;
addEntry(); addEntry(list);
} }
myPC++; myPC++;
} }
@ -287,7 +287,7 @@ void DiStella::disasm(uInt32 distart, int pass)
bytes++; bytes++;
if (bytes == 17) if (bytes == 17)
{ {
addEntry(); addEntry(list);
myBuf << " ' '.byte $" << HEX2 << (int)mem[myPC]; myBuf << " ' '.byte $" << HEX2 << (int)mem[myPC];
bytes = 1; bytes = 1;
} }
@ -299,9 +299,9 @@ void DiStella::disasm(uInt32 distart, int pass)
if (pass == 3) if (pass == 3)
{ {
addEntry(); addEntry(list);
myBuf << " ' ' "; myBuf << " ' ' ";
addEntry(); addEntry(list);
} }
} }
else else
@ -321,7 +321,7 @@ void DiStella::disasm(uInt32 distart, int pass)
amode = ourLookup[op].addr_mode; amode = ourLookup[op].addr_mode;
if (myAppData.disp_data) if (myAppData.disp_data)
{ {
for (i = 0; i < ourCLength[amode]; i++) for (int i = 0; i < ourCLength[amode]; i++)
if (pass == 3) if (pass == 3)
myBuf << HEX2 << (int)mem[myPC+i] << " "; myBuf << HEX2 << (int)mem[myPC+i] << " ";
@ -376,7 +376,7 @@ void DiStella::disasm(uInt32 distart, int pass)
/* Line information is already printed; append .byte since last instruction will /* Line information is already printed; append .byte since last instruction will
put recompilable object larger that original binary file */ put recompilable object larger that original binary file */
myBuf << ".byte $" << HEX2 << op; myBuf << ".byte $" << HEX2 << op;
addEntry(); addEntry(list);
if (myPC == myAppData.end) if (myPC == myAppData.end)
{ {
@ -387,7 +387,7 @@ void DiStella::disasm(uInt32 distart, int pass)
op = mem[myPC++]; op = mem[myPC++];
myBuf << ".byte $" << HEX2 << (int)op; myBuf << ".byte $" << HEX2 << (int)op;
addEntry(); addEntry(list);
} }
} }
myPCEnd = myAppData.end + myOffset; myPCEnd = myAppData.end + myOffset;
@ -411,7 +411,7 @@ void DiStella::disasm(uInt32 distart, int pass)
strcat(nextline,linebuff); strcat(nextline,linebuff);
myBuf << nextline; myBuf << nextline;
addEntry(); addEntry(list);
strcpy(nextline,""); strcpy(nextline,"");
strcpy(nextlinebytes,""); strcpy(nextlinebytes,"");
} }
@ -809,15 +809,15 @@ void DiStella::disasm(uInt32 distart, int pass)
if (strlen(nextline) <= 15) if (strlen(nextline) <= 15)
{ {
/* Print spaces to align cycle count data */ /* Print spaces to align cycle count data */
for (int charcnt=0;charcnt<15-strlen(nextline);charcnt++) for (uInt32 charcnt=0;charcnt<15-strlen(nextline);charcnt++)
myBuf << " "; myBuf << " ";
} }
myBuf << ";" << dec << (int)ourLookup[op].cycles << "'" << nextlinebytes; myBuf << ";" << dec << (int)ourLookup[op].cycles << "'" << nextlinebytes;
addEntry(); addEntry(list);
if (op == 0x40 || op == 0x60) if (op == 0x40 || op == 0x60)
{ {
myBuf << " ' ' "; myBuf << " ' ' ";
addEntry(); addEntry(list);
} }
strcpy(nextline,""); strcpy(nextline,"");
@ -916,23 +916,48 @@ void DiStella::showgfx(uInt8 c)
{ {
int i; int i;
printf("|"); myBuf << "|";
for(i = 0;i < 8; i++) for(i = 0;i < 8; i++)
{ {
if (c > 127) if (c > 127)
printf("X"); myBuf << "X";
else else
printf(" "); myBuf << " ";
c = c << 1; c = c << 1;
} }
printf("|"); myBuf << "|";
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DiStella::addEntry() void DiStella::addEntry(DisassemblyList& list)
{ {
cout << myBuf.str() << endl; const string& line = myBuf.str();
DisassemblyTag tag;
if(line[0] == ' ')
tag.address = 0;
else
myBuf >> setw(4) >> hex >> tag.address;
if(line[5] != ' ')
tag.label = line.substr(5, 5);
switch(line[11])
{
case ' ':
tag.disasm = " ";
break;
case '.':
tag.disasm = line.substr(11);
break;
default:
tag.disasm = line.substr(11, 17);
tag.bytes = line.substr(29);
break;
}
list.push_back(tag);
myBuf.str(""); myBuf.str("");
++myLineCount; ++myLineCount;
} }
@ -1296,26 +1321,12 @@ int main(int ac, char* av[])
DiStella dis; DiStella dis;
DisassemblyList list; DisassemblyList list;
int count = dis.disassemble(list, av[1]); int count = dis.disassemble(list, 0xfff-3, av[1]);
#if 0
ostringstream buf;
int x = 0x0abc;
buf << uppercase << hex << setw(4) << setfill('0') << x << "'L" << setw(4) << setfill('0') << x << "'";
cout << buf.str() << endl;
buf.str("");
/*
printf("%.4X'L%.4X'", myPC+myOffset, myPC+myOffset);
else
printf("%.4X' '", myPC+myOffset);
*/
#endif
for(uInt32 i = 0; i < list.size(); ++i) for(uInt32 i = 0; i < list.size(); ++i)
{ {
const DisassemblyTag& tag = list[i]; const DisassemblyTag& tag = list[i];
printf("%.4X | %s %s\n", tag.address, tag.disasm.c_str(), tag.bytes.c_str()); printf("%.4X|%5s|%s|%s|\n", tag.address, tag.label.c_str(), tag.disasm.c_str(), tag.bytes.c_str());
} }
return 0; return 0;

View File

@ -29,7 +29,8 @@
//// The following will go in CartDebug //// The following will go in CartDebug
struct DisassemblyTag { struct DisassemblyTag {
int address; uInt16 address;
string label;
string disasm; string disasm;
string bytes; string bytes;
}; };
@ -38,10 +39,13 @@
/** /**
This class is a wrapper around the Distella code. Much of the code remains This class is a wrapper around the Distella code. Much of the code remains
exactly the same. All 7800-related stuff has been removed, as well as all exactly the same, except that generated data is now redirected to a
commandline options. For now, the only configurable item is whether to DisassemblyList structure rather than being printed.
automatically determine code vs. data sections (which is on by default).
Over time, some of the configurability of Distella may be added again. All 7800-related stuff has been removed, as well as all commandline options.
For now, the only configurable item is whether to automatically determine
code vs. data sections (which is on by default). Over time, some of the
configurability of Distella may be added again.
@author Stephen Anthony @author Stephen Anthony
*/ */
@ -52,7 +56,7 @@ class DiStella
~DiStella(); ~DiStella();
public: public:
uInt32 disassemble(DisassemblyList& list, const char* datafile, bool autocode = true); uInt32 disassemble(DisassemblyList& list, uInt16 PC, const char* datafile, bool autocode = true);
private: private:
// Marked bits // Marked bits
@ -68,22 +72,22 @@ class DiStella
REACHABLE = 1 << 4 /* disassemble-able code segments */ REACHABLE = 1 << 4 /* disassemble-able code segments */
}; };
// Indicate that a new line of disassembly has been performed // Indicate that a new line of disassembly has been completed
// In the original Distella code, this indicated a new line to be printed. // In the original Distella code, this indicated a new line to be printed
// Here, we add a new entry to the DisassemblyList // Here, we add a new entry to the DisassemblyList
void addEntry(); void addEntry(DisassemblyList& list);
// These functions are part of the original Distella code // These functions are part of the original Distella code
uInt32 filesize(FILE *stream); uInt32 filesize(FILE *stream);
uInt32 read_adr(); uInt32 read_adr();
int file_load(const char* file); int file_load(const char* file);
void disasm(uInt32 distart, int pass); void disasm(DisassemblyList& list, uInt32 distart, int pass);
int mark(uInt32 address, MarkType bit); int mark(uInt32 address, MarkType bit);
int check_bit(uInt8 bitflags, int i); int check_bit(uInt8 bitflags, int i);
void showgfx(uInt8 c); void showgfx(uInt8 c);
private: private:
ostringstream myBuf; stringstream myBuf;
queue<uInt16> myAddressQueue; queue<uInt16> myAddressQueue;
uInt32 myOffset, myPC, myPCBeg, myPCEnd, myLineCount; uInt32 myOffset, myPC, myPCBeg, myPCEnd, myLineCount;