--- hatari/src/debug/68kDisass.c 2019/04/09 08:49:26 1.1.1.1 +++ hatari/src/debug/68kDisass.c 2019/04/09 08:54:22 1.1.1.5 @@ -1,8 +1,8 @@ /*** * 68k disassembler, written 2010 by Markus Fritze, www.sarnau.com * - * This file is distributed under the GNU Public License, version 2 or at - * your option any later version. Read the file gpl.txt for details. + * This file is distributed under the GNU General Public License, version 2 + * or at your option any later version. Read the file gpl.txt for details. ***/ #include @@ -13,8 +13,10 @@ #include "config.h" #include "sysdeps.h" #include "main.h" +#include "configuration.h" #include "newcpu.h" #include "paths.h" +#include "profile.h" #include "tos.h" #include "68kDisass.h" @@ -25,18 +27,21 @@ typedef enum { doptNoBrackets = 1, // hide brackets around absolute addressing doptOpcodesSmall = 2, // opcodes are small letters doptRegisterSmall = 4, // register names are small letters - doptStackSP = 8, // stack pointer is named "SP" instead of "A7" (except for MOVEM) + doptStackSP = 8 // stack pointer is named "SP" instead of "A7" (except for MOVEM) } Diss68kOptions; static Diss68kOptions options = doptOpcodesSmall | doptRegisterSmall | doptStackSP | doptNoBrackets; +/* all options */ +static const Diss68kOptions optionsMask = doptOpcodesSmall | doptRegisterSmall | doptStackSP | doptNoBrackets; + // values <0 will hide the group -static int optionPosAddress = 0; // current address -static int optionPosHexdump = 10; // 16-bit words at this address -static int optionPosLabel = 35; // label, if defined -static int optionPosOpcode = 47; // opcode -static int optionPosOperand = 57; // operands for the opcode -static int optionPosComment = 82; // comment, if defined +static int optionPosAddress = 0; // current address +static int optionPosHexdump = 10; // 16-bit words at this address +static int optionPosLabel = 35; // label, if defined +static int optionPosOpcode = 47; // opcode +static int optionPosOperand = 57; // operands for the opcode +static int optionPosComment = 82; // comment, if defined /*** * Motorola 16-/32-Bit Microprocessor and coprocessor types @@ -83,7 +88,7 @@ typedef enum { dtASCString, // a 0-byte terminated ASCII string dtPointer, // a generic 32-bit pointer dtFunctionPointer, // a 32-bit pointer to a function - dtStringArray, // a specific number of ASCII bytes + dtStringArray // a specific number of ASCII bytes } Disass68kDataType; typedef struct { @@ -126,22 +131,29 @@ static inline unsigned short Disass68kGe static int Disass68kLoadTextFile(const char *filename, char **filebuf) { long index; - + long fileLength; + int lineCount; + char *fbuf; + FILE *f; + if(filebuf) *filebuf = NULL; - FILE *f = fopen(filename, "r"); + f = fopen(filename, "r"); if(!f) return 0; if(fseek(f, 0, SEEK_END)) return 0; - long fileLength = ftell(f); - if(!fileLength) return 0; + fileLength = ftell(f); + if(fileLength <= 0) return 0; if(fseek(f, 0, SEEK_SET)) return 0; - char *fbuf = malloc(fileLength); + fbuf = malloc(fileLength); if(!fbuf) return 0; if((size_t)fileLength != fread(fbuf, sizeof(char), fileLength, f)) + { + free(fbuf); return 0; - int lineCount = 0; + } + lineCount = 0; for(index=0; indexaddr; + if(offset < 0 || offset >= dse->count * dse->size) continue; @@ -370,7 +392,7 @@ static Disass68kDataType Disass68kType(l } *count = 1; - const disStructEntry *se = &disStructEntries[dse->structIndex]; + se = &disStructEntries[dse->structIndex]; for(j=0; jcount; ++j) { const disStructElement *e = &se->elements[j]; @@ -402,18 +424,20 @@ static const char *Disass68kSymbolName(l for(i=0; iaddr; + int offset = addr - dse->addr; + int reminder; + if(offset < 0 || offset >= dse->count * dse->size) continue; if(dse->name[0] == 0) return NULL; - int reminder = offset % dse->size; + reminder = offset % dse->size; offset /= dse->size; - static char symbolName[128]; strcpy(symbolName, dse->name); if(offset) sprintf(symbolName+strlen(symbolName), "+%d*%d", dse->size, offset); @@ -461,10 +485,10 @@ static const char *Disass68kNumber(int v sprintf(numString, "%d", val); } else { // 4 characters/numbers or underscore (e.g. for cookies) - char c0 = (val >> 24) & 0xFF; - char c1 = (val >> 16) & 0xFF; - char c2 = (val >> 8) & 0xFF; - char c3 = (val >> 0) & 0xFF; + unsigned char c0 = (val >> 24) & 0xFF; + unsigned char c1 = (val >> 16) & 0xFF; + unsigned char c2 = (val >> 8) & 0xFF; + unsigned char c3 = (val >> 0) & 0xFF; if((isalnum(c0) || c0 == '_') && (isalnum(c1) || c1 == '_') && (isalnum(c2) || c2 == '_') && (isalnum(c3) || c3 == '_')) { sprintf(numString, "'%c%c%c%c'", c0, c1, c2, c3); @@ -556,14 +580,15 @@ static const char *Disass68kSpecialRegis case REG_FPU_FPIAR: sp = "FPIAR"; break; // unknown register => unknown opcode! - default: break; + default: return NULL; } + if(options & doptRegisterSmall) { + char *bp; strcpy(buf, sp); - char *bp = buf; - for(; *bp; ++bp) - *bp = tolower(*bp); + for (bp = buf; *bp; ++bp) + *bp = tolower((unsigned char)*bp); return buf; } return sp; @@ -605,7 +630,8 @@ static char *Disass68kEA(char *disassbu int reg = ea & 7; const char *sp; long val; - val = 0; + char regName[3]; + signed long pcoffset; disassbuf[0] = 0; switch(ea) @@ -686,7 +712,7 @@ static char *Disass68kEA(char *disassbu xn = (eWord1 >> 12) & 0x0F; // Register D0..D7/A0..A7 c = ((eWord1 >> 11) & 1) ? 'l' : 'w'; // Word/Long-Word Index Size 0 = Sign-Extended Word 1 = Long Word scale = (eWord1 >> 9) & 3; // Scale Factor 00 = 1 01 = 2 10 = 4 11 = 8 - char regName[3]; + if(ea == 0x3B) { sp = Disass68kSpecialRegister(REG_PC); @@ -698,6 +724,8 @@ static char *Disass68kEA(char *disassbu if((eWord1 & 0x0100) == 0) { + const char *numStr; + // BRIEF EXTENSION WORD FORMAT if(ea == 0x3B) { @@ -710,7 +738,7 @@ static char *Disass68kEA(char *disassbu // Address Register Indirect with Index (8-Bit Displacement) Mode // (d8 ,An, Xn.SIZE*SCALE) - const char *numStr = Disass68kNumber(eWord1 & 0xFF); + numStr = Disass68kNumber(eWord1 & 0xFF); if(numStr[0] == '0' && numStr[1] == 0) numStr = ""; @@ -756,11 +784,12 @@ static char *Disass68kEA(char *disassbu } else { // FULL EXTENSION WORD FORMAT - int bs = (eWord1 >> 7) & 1; // Base Register Suppress 0 = Base Register Added 1 = Base Register Suppressed - int is = (eWord1 >> 6) & 1; // Index Suppress 0 = Evaluate and Add Index Operand 1 = Suppress Index Operand - int bdSize = (eWord1 >> 4) & 3; // Base Displacement Size 00 = Reserved 01 = Null Displacement 10 = Word Displacement 11 = Long Displacement - int iis = eWord1 & 7; // Index/Indirect Selection Indirect and Indexing Operand Determined in Conjunction with Bit 6, Index Suppress + int bs = (eWord1 >> 7) & 1; // Base Register Suppress 0 = Base Register Added 1 = Base Register Suppressed + int is = (eWord1 >> 6) & 1; // Index Suppress 0 = Evaluate and Add Index Operand 1 = Suppress Index Operand + int bdSize = (eWord1 >> 4) & 3; // Base Displacement Size 00 = Reserved 01 = Null Displacement 10 = Word Displacement 11 = Long Displacement + int iis = eWord1 & 7; // Index/Indirect Selection Indirect and Indexing Operand Determined in Conjunction with Bit 6, Index Suppress bool prefixComma; + long bd, od; // reserved, has to be 0 if((eWord1 & 8) != 0 || bdSize == 0 || (is && iis > 3) || iis == 4) @@ -779,7 +808,7 @@ static char *Disass68kEA(char *disassbu break; } - long bd = 0; + bd = 0; switch(bdSize) { case 3: @@ -849,7 +878,7 @@ static char *Disass68kEA(char *disassbu strcat(disassbuf, "]"); prefixComma = true; } - long od = 0; + od = 0; switch(iis & 3) { case 3: @@ -1025,7 +1054,7 @@ static char *Disass68kEA(char *disassbu case 0x0102: // PC relative jump, like for BRA and friends if((allowedEAs & EA_PCDisplacement) != EA_PCDisplacement) break; - signed long pcoffset = 0; + pcoffset = 0; switch(size) { case 1: pcoffset = (signed char)parameterValue; @@ -1252,7 +1281,7 @@ typedef enum { ofFPUMOVE, ofFMOVECR, ofFPU3Reg, - ofLineA, + ofLineA } Disass68kOpcodeFormat; @@ -1263,7 +1292,7 @@ typedef enum { typedef const struct { int cpuMask; unsigned long opcodeMask[2*5]; - char operationSize[4]; + signed char operationSize[4]; char op[5]; const char *opcodeName; int parameter[5]; @@ -1683,155 +1712,168 @@ static const OpcodeTableStruct OpcodeTab { MC68040|MC68060|MC_FPU, {0xffc0, 0xf100|(FPU_COPROC_ID<<9)}, {0}, {ofEa}, "FSAVE", {EA_Dn|EA_An|EA_piAn|EA_Immed} }, { MC68040|MC68060|MC_FPU, {0xffc0, 0xf140|(FPU_COPROC_ID<<9)}, {0}, {ofEa}, "FRESTORE", {EA_Dn|EA_An|EA_piAn|EA_Immed} }, - { } + { 0 } }; static int Disass68k(long addr, char *labelBuffer, char *opcodeBuffer, char *operandBuffer, char *commentBuffer) { long baseAddr = addr; int val; - const char *sp; + int i; + int count = 0; + char addressLabel[256]; + char cmtBuffer[256]; + Disass68kDataType type; + int index; + long opcodeAddr; + labelBuffer[0] = 0; opcodeBuffer[0] = 0; operandBuffer[0] = 0; commentBuffer[0] = 0; - int i; - int count = 0; - char addressLabel[256]; - char cmtBuffer[256]; - Disass68kDataType type = Disass68kType(baseAddr, addressLabel, cmtBuffer, &count); + type = Disass68kType(baseAddr, addressLabel, cmtBuffer, &count); if(addressLabel[0]) sprintf(labelBuffer, "%s:", addressLabel); sprintf(commentBuffer, "%s", cmtBuffer); switch(type) { - case dtByte:if(count > 8) - count = 8; - strcpy(opcodeBuffer,"DC.B"); - for(i=0; i 0) - strcat(operandBuffer, ","); - char hbuf[16]; - unsigned short val = Disass68kGetWord(addr+(i & ~1)); - if(i & 1) - val &= 0xFF; - else - val = val >> 8; - sprintf(hbuf,"$%2.2x", val); - strcat(operandBuffer, hbuf); - } - return count; - - case dtWord:if(count > 4) - count = 4; - strcpy(opcodeBuffer,"DC.W"); - for(i=0; i 0) - strcat(operandBuffer, ","); - char hbuf[16]; - sprintf(hbuf,"$%4.4x", Disass68kGetWord(addr+i*2)); - strcat(operandBuffer, hbuf); - } - return count * 2; - - case dtLong:if(count > 2) - count = 2; - strcpy(opcodeBuffer,"DC.L"); - for(i=0; i 0) - strcat(operandBuffer, ","); - char hbuf[16]; - sprintf(hbuf,"$%8.8x", (Disass68kGetWord(addr+i*4) << 16) | Disass68kGetWord(addr+i*4+2)); - strcat(operandBuffer, hbuf); - } - return count * 4; + case dtByte: + if(count > 8) + count = 8; + strcpy(opcodeBuffer,"DC.B"); + for (i = 0; i < count; ++i) + { + char hbuf[16]; + unsigned short val; + + if((i & 7) > 0) + strcat(operandBuffer, ","); + val = Disass68kGetWord(addr+(i & ~1)); + if(i & 1) + val &= 0xFF; + else + val = val >> 8; + sprintf(hbuf,"$%2.2x", val); + strcat(operandBuffer, hbuf); + } + return count; + + case dtWord: + if(count > 4) + count = 4; + strcpy(opcodeBuffer,"DC.W"); + for (i = 0; i < count; ++i) + { + char hbuf[16]; + if((i & 3) > 0) + strcat(operandBuffer, ","); + sprintf(hbuf,"$%4.4x", Disass68kGetWord(addr+i*2)); + strcat(operandBuffer, hbuf); + } + return count * 2; + + case dtLong: + if(count > 2) + count = 2; + strcpy(opcodeBuffer,"DC.L"); + for (i = 0; i < count; ++i) + { + char hbuf[16]; + if((i & 1) > 0) + strcat(operandBuffer, ","); + sprintf(hbuf,"$%8.8x", (Disass68kGetWord(addr+i*4) << 16) | Disass68kGetWord(addr+i*4+2)); + strcat(operandBuffer, hbuf); + } + return count * 4; case dtStringArray: - { - strcpy(opcodeBuffer,"DC.B"); - strcat(operandBuffer, "'"); - char *sp = operandBuffer + strlen(operandBuffer); - for(i=0; i < count; ++i) - { - unsigned short val = Disass68kGetWord(addr+(i & ~1)); - if(i & 1) - val &= 0xFF; - else - val = val >> 8; - if(val == 0) - break; - switch(val) - { - case 9: *sp++ = '\\'; *sp++ = 't'; break; - case 10: *sp++ = '\\'; *sp++ = 'n'; break; - case 13: *sp++ = '\\'; *sp++ = 'r'; break; - default: - if(val >= 0x20 && val <= 0x7E) - *sp++ = val; - } - } - *sp = 0; - strcat(sp, "'"); - return count; - } + { + char *sp; + strcpy(opcodeBuffer,"DC.B"); + strcat(operandBuffer, "'"); + sp = operandBuffer + strlen(operandBuffer); + for (i = 0; i < count; ++i) + { + unsigned short val = Disass68kGetWord(addr+(i & ~1)); + if(i & 1) + val &= 0xFF; + else + val = val >> 8; + if(val == 0) + break; + switch(val) + { + case 9: *sp++ = '\\'; *sp++ = 't'; break; + case 10: *sp++ = '\\'; *sp++ = 'n'; break; + case 13: *sp++ = '\\'; *sp++ = 'r'; break; + default: + if(val >= 0x20 && val <= 0x7E) + *sp++ = val; + } + } + *sp = 0; + strcat(sp, "'"); + return count; + } case dtASCString: + { + int count = 1; + unsigned short val = Disass68kGetWord(addr+0); + strcpy(opcodeBuffer,"DC.B"); + if((val >> 8) == 0) + { + strcat(operandBuffer, "0"); + } else { + char *sp; + strcat(operandBuffer, "'"); + sp = operandBuffer + strlen(operandBuffer); + for(i=0; ; ++i) + { + unsigned short val = Disass68kGetWord(addr+(i & ~1)); + if(i & 1) + val &= 0xFF; + else + val = val >> 8; + if(val == 0) + break; + switch(val) { - int count = 1; - unsigned short val = Disass68kGetWord(addr+0); - strcpy(opcodeBuffer,"DC.B"); - if((val >> 8) == 0) - { - strcat(operandBuffer, "0"); - } else { - strcat(operandBuffer, "'"); - char *sp = operandBuffer + strlen(operandBuffer); - for(i=0; ; ++i) - { - unsigned short val = Disass68kGetWord(addr+(i & ~1)); - if(i & 1) - val &= 0xFF; - else - val = val >> 8; - if(val == 0) - break; - switch(val) - { - case 9: *sp++ = '\\'; *sp++ = 't'; break; - case 10: *sp++ = '\\'; *sp++ = 'n'; break; - case 13: *sp++ = '\\'; *sp++ = 'r'; break; - default: - if(val >= 0x20 && val <= 0x7E) - *sp++ = val; - } - ++count; - } - *sp = 0; - strcat(sp, "',0"); - } - return (count + 1) & ~1; + case 9: *sp++ = '\\'; *sp++ = 't'; break; + case 10: *sp++ = '\\'; *sp++ = 'n'; break; + case 13: *sp++ = '\\'; *sp++ = 'r'; break; + default: + if(val >= 0x20 && val <= 0x7E) + *sp++ = val; } + ++count; + } + *sp = 0; + strcat(sp, "',0"); + } + return (count + 1) & ~1; + } case dtPointer: case dtFunctionPointer: - val = (Disass68kGetWord(addr) << 16) | Disass68kGetWord(addr+2); - sp = Disass68kSymbolName(val, 2); - strcpy(opcodeBuffer,"DC.L"); - if(sp) - sprintf(operandBuffer,"%s", sp); - else - sprintf(operandBuffer,"$%6.6x", val); - return 4; + { + const char *sp; + val = (Disass68kGetWord(addr) << 16) | Disass68kGetWord(addr+2); + sp = Disass68kSymbolName(val, 2); + strcpy(opcodeBuffer,"DC.L"); + if(sp) + sprintf(operandBuffer,"%s", sp); + else + sprintf(operandBuffer,"$%6.6x", val); + return 4; + } default: break; } - int index = 0; - long opcodeAddr = addr; + index = 0; + opcodeAddr = addr; more: addr = opcodeAddr; @@ -1844,19 +1886,28 @@ more: while(1) { + unsigned short opcode[5]; + unsigned int i; OpcodeTableStruct *ots = &OpcodeTable[index++]; + int size; + char sizeChar = 0; + char *dbuf; + int ea; + unsigned int maxop; + if(ots->opcodeName == NULL) break; if((ots->cpuMask & optionCPUTypeMask) == 0) // CPU doesn't match? continue; // search for the opcode plus up to 2 extension words - unsigned short opcode[5] = {}; - unsigned int i; for(i=0; i<5; ++i) { if(!ots->opcodeMask[i*2]) + { + opcode[i] = 0; break; + } opcode[i] = Disass68kGetWord(addr); if(((ots->opcodeMask[i*2] & 0xFFFF) & opcode[i]) != ots->opcodeMask[i*2+1]) goto more; @@ -1864,8 +1915,7 @@ more: } // find out the size of the opcode operand - int size = ots->operationSize[0]; - char sizeChar = 0; + size = ots->operationSize[0]; if(size < 0) // custom size? { int opcodeOffset = ots->operationSize[1] >> 4; @@ -1902,7 +1952,7 @@ more: } // copy the opcode plus a necessary TAB for the operand - char *dbuf = opcodeBuffer; + dbuf = opcodeBuffer; for(i=0; ots->opcodeName[i]; ++i) { char c = ots->opcodeName[i]; @@ -1913,6 +1963,7 @@ more: static const char *sccCond[16] = { "T", "F", "HI", "LS", "CC", "CS", "NE", "EQ", "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" }; static const char *dbCond[16] = { "T", "RA", "HI", "LS", "CC", "CS", "NE", "EQ", "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" }; static const char *fpuCond[64] = { "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR", "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T", "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE", "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST" }; + char buf[8]; const char *sp = NULL; switch(ots->opcodeName[++i]) @@ -1940,12 +1991,11 @@ more: { if(options & doptOpcodesSmall) { - char buf[8]; + char *bp; strcpy(buf, sp); sp = buf; - char *bp = buf; - for(; *bp; ++bp) - *bp = tolower(*bp); + for (bp = buf; *bp; ++bp) + *bp = tolower((unsigned char)*bp); } strcpy(dbuf, sp); dbuf += strlen(sp); @@ -1956,16 +2006,20 @@ more: if(c == '?') // size mask c = sizeChar; if(options & doptOpcodesSmall) - c = tolower(c); + c = tolower((unsigned char)c); *dbuf++ = c; } *dbuf = 0; // Parse the EAs for all operands - int ea = opcode[0] & 0x3F; + ea = opcode[0] & 0x3F; dbuf = operandBuffer; - for(i=0; i<(sizeof(ots->op)/sizeof(ots->op[0])); ++i) + + maxop=(sizeof(ots->op)/sizeof(ots->op[0])); + for(i=0; iop[i]) { case ofNone: // nothing @@ -2155,7 +2209,7 @@ more: char regFP2 = options & doptRegisterSmall ? 'p' : 'P'; dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 1, EA_ImmedParameter, opcode[1] & 0x7F, ots->disassFlag); if(!dbuf) goto more; - int reg = (opcode[1] >> 7) & 7; + reg = (opcode[1] >> 7) & 7; *dbuf++ = ','; *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+reg; *dbuf = 0; @@ -2324,7 +2378,6 @@ more: case ofLineA: { int lineAVal = opcode[0] & 0xFFF; - dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 2, EA_ImmedParameter, lineAVal, ots->disassFlag); const char *lineAStr[16] = { "Line-A Initialization", "Put pixel", "Get pixel", @@ -2342,6 +2395,7 @@ more: "Copy raster form", "Seedfill" }; + dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 2, EA_ImmedParameter, lineAVal, ots->disassFlag); if(lineAVal < 16) strcat(commentBuffer, lineAStr[lineAVal]); } @@ -2353,7 +2407,7 @@ more: if(!dbuf) goto more; // does another operand follow => add separator - if(ots->op[i+1] != ofNone) + if ( (i+1op[i+1] != ofNone) ) *dbuf++ = ','; } return addr-baseAddr; @@ -2388,8 +2442,8 @@ static void Disass68k_loop (FILE *f, uae isInit = true; } - while (cnt-- > 0) { - int addrWidth = 6; // 6 on an ST, 8 on a TT + while (cnt-- > 0) { + const int addrWidth = 6; // 6 on an ST, 8 on a TT char lineBuffer[1024]; char addressBuffer[32]; @@ -2398,16 +2452,18 @@ static void Disass68k_loop (FILE *f, uae char opcodeBuffer[64]; char operandBuffer[256]; char commentBuffer[256]; - int len = Disass68k(addr, labelBuffer, opcodeBuffer, operandBuffer, commentBuffer); + int plen, len, j; + + len = Disass68k(addr, labelBuffer, opcodeBuffer, operandBuffer, commentBuffer); if(!len) break; sprintf(addressBuffer, "$%*.*x :", addrWidth,addrWidth, addr); hexdumpBuffer[0] = 0; - int plen = len; + plen = len; if(plen > 80 && (!strncmp(opcodeBuffer, "DC.", 3) || !strncmp(opcodeBuffer, "dc.", 3))) plen = ((optionPosLabel - optionPosHexdump) / 5) * 2; - int j; + for(j=0; j 0) @@ -2439,33 +2495,189 @@ static void Disass68k_loop (FILE *f, uae } Disass68kComposeStr(lineBuffer, operandBuffer, optionPosOperand, 0); } - if(commentBuffer[0] && optionPosComment >= 0) + if (optionPosComment >= 0) { - Disass68kComposeStr(lineBuffer, " ;", optionPosComment, 0); - Disass68kComposeStr(lineBuffer, commentBuffer, optionPosComment+3, 0); + float percentage; + Uint32 count, cycles, misses; + if (Profile_CpuAddressData(addr, &percentage, &count, &cycles, &misses)) + { + sprintf(commentBuffer, "%5.2f%% (%u, %u, %u)", percentage, count, cycles, misses); + Disass68kComposeStr(lineBuffer, commentBuffer, optionPosComment+1, 0); + } + /* show comments only if profile data is missing */ + else if (commentBuffer[0]) + { + Disass68kComposeStr(lineBuffer, " ;", optionPosComment, 0); + Disass68kComposeStr(lineBuffer, commentBuffer, optionPosComment+3, 0); + } } - - fprintf(f, "%s\n", lineBuffer); + addr += len; + if (f) + fprintf(f, "%s\n", lineBuffer); // if(strstr(opcodeBuffer, "RTS") || strstr(opcodeBuffer, "RTE") || strstr(opcodeBuffer, "JMP") // || strstr(opcodeBuffer, "rts") || strstr(opcodeBuffer, "rte") || strstr(opcodeBuffer, "jmp")) // fprintf(f, "\n"); - addr += len; } if (nextpc) *nextpc = addr; } -/* - * Disasm should be called from Hatari's sources to use either uae's built in - * disassembler (DISASM_ENGINE_UAE) or the stand alone disassembler above (DISASM_ENGINE_EXT) +/** + * Calculate next PC address from given one, without output + * @return next PC address + */ +Uint32 Disasm_GetNextPC(Uint32 pc) +{ + uaecptr nextpc; + Disass68k_loop (NULL, pc, &nextpc, 1); + return nextpc; +} + +/** + * Call disassembly using the selected disassembly method, + * either internal UAE one, or the stand alone disassembler above, + * whichever is selected in Hatari configuration + */ +void Disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) +{ + if (ConfigureParams.Debugger.bDisasmUAE) + m68k_disasm (f, addr, nextpc, cnt); + else + Disass68k_loop (f, addr, nextpc, cnt); +} + +static void Disasm_CheckOptionEngine(void) +{ + if (ConfigureParams.Debugger.bDisasmUAE) + fputs("WARNING: disassembly options are supported only for '--disasm ext'!\n", stderr); +} + +/** + * query disassembly output column positions. + */ +void Disasm_GetColumns(int *pos) +{ + pos[DISASM_COLUMN_ADDRESS] = optionPosAddress; + pos[DISASM_COLUMN_HEXDUMP] = optionPosHexdump; + pos[DISASM_COLUMN_LABEL] = optionPosLabel; + pos[DISASM_COLUMN_OPCODE] = optionPosOpcode; + pos[DISASM_COLUMN_OPERAND] = optionPosOperand; + pos[DISASM_COLUMN_COMMENT] = optionPosComment; +} + +/** + * set disassembly output column positions. */ +void Disasm_SetColumns(int *pos) +{ + Disasm_CheckOptionEngine(); + optionPosAddress = pos[DISASM_COLUMN_ADDRESS]; + optionPosHexdump = pos[DISASM_COLUMN_HEXDUMP]; + optionPosLabel = pos[DISASM_COLUMN_LABEL]; + optionPosOpcode = pos[DISASM_COLUMN_OPCODE]; + optionPosOperand = pos[DISASM_COLUMN_OPERAND]; + optionPosComment = pos[DISASM_COLUMN_COMMENT]; +} + +/** + * function to disable given disassembly output 'column'. + * input is current column positions in 'oldcols' array and + * output is new column positions/values in 'newcols' array. + * It's safe to use same array for both. + */ +void Disasm_DisableColumn(int column, int *oldcols, int *newcols) +{ + int i, diff = 0; + + assert(column >= 0 && column < DISASM_COLUMNS); + if (column+1 < DISASM_COLUMNS) + diff = oldcols[column+1] - oldcols[column]; + + for (i = 0; i < DISASM_COLUMNS; i++) + { + if (i && oldcols[i-1] > oldcols[i]) + { + printf("WARNING: disassembly columns aren't in the expected order!\n"); + return; + } + if (i < column) + newcols[i] = oldcols[i]; + else if (i > column) + newcols[i] = oldcols[i] - diff; + else + newcols[column] = DISASM_COLUMN_DISABLE; + } +} -void Disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt , int DisasmEngine) +/** + * Get current disassembly output option flags + * @return current output flags + */ +int Disasm_GetOptions(void) { - if ( DisasmEngine == DISASM_ENGINE_UAE ) - return m68k_disasm (f, addr, nextpc, cnt); - else if ( DisasmEngine == DISASM_ENGINE_EXT ) - return Disass68k_loop (f, addr, nextpc, cnt); + return options; } +/** + * Parse disasm command line option argument + * @return error string (""=silent 'error') or NULL for success. + */ +const char *Disasm_ParseOption(const char *arg) +{ + if (strcasecmp(arg, "help") == 0) + { + const struct { + int flag; + const char *desc; + } option[] = { + { doptNoBrackets, "no brackets around absolute addressing" }, + { doptOpcodesSmall, "opcodes in small letters" }, + { doptRegisterSmall, "register names in small letters" }, + { doptStackSP, "stack pointer as 'SP', not 'A7'" }, + { 0, NULL } + }; + int i; + fputs("Disassembly settings:\n" + "\tuae - use CPU core internal disassembler which has better\n" + "\t instruction support\n" + "\text - use external disassembler which has nicer output\n" + "\t and supports options below\n" + "\t - disassembly output option flags\n" + "Flag values:\n", stderr); + for (i = 0; option[i].desc; i++) { + assert(option[i].flag == (1 << i)); + fprintf(stderr, "\t%d: %s\n", option[i].flag, option[i].desc); + } + fprintf(stderr, "Current settings are:\n\t--disasm %s --disasm %d\n", + ConfigureParams.Debugger.bDisasmUAE ? "uae" : "ext", + ConfigureParams.Debugger.nDisasmOptions); + return ""; + } + if (strcasecmp(arg, "uae") == 0) + { + fputs("Selected UAE CPU core internal disassembler.\n", stderr); + ConfigureParams.Debugger.bDisasmUAE = true; + return NULL; + } + if (strcasecmp(arg, "ext") == 0) + { + fputs("Selected external disassembler.\n", stderr); + fprintf(stderr, "Disassembly output flags are %d.\n", options); + ConfigureParams.Debugger.bDisasmUAE = false; + return NULL; + } + if (isdigit((unsigned char)*arg)) + { + int newopt = atoi(arg); + if ((newopt|optionsMask) != optionsMask) + { + return "unknown flags in the bitmask"; + } + fprintf(stderr, "Changed CPU disassembly output flags from %d to %d.\n", options, newopt); + ConfigureParams.Debugger.nDisasmOptions = options = newopt; + Disasm_CheckOptionEngine(); + return NULL; + } + return "invalid disasm option"; +}