# HG changeset patch # User Mike Pavone # Date 1356890118 28800 # Node ID ab50421b1b7a104677ea8c5c96c23bbc6179dd7e # Parent c4d10c2aaee2a6a54a836adf82056617e72a9387 Improve disassembler diff -r c4d10c2aaee2 -r ab50421b1b7a 68kinst.c --- a/68kinst.c Sun Dec 30 09:55:07 2012 -0800 +++ b/68kinst.c Sun Dec 30 09:55:18 2012 -0800 @@ -1156,7 +1156,7 @@ "le" }; -int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma) +int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address) { char * c = need_comma ? "," : ""; switch(decoded->addr_mode) @@ -1179,11 +1179,23 @@ case MODE_IMMEDIATE_WORD: return sprintf(dst, (decoded->params.immed <= 128 ? "%s #%d" : "%s #$%X"), c, decoded->params.immed); case MODE_ABSOLUTE_SHORT: - return sprintf(dst, "%s $%X.w", c, decoded->params.immed); + if (labels) { + return sprintf(dst, "%s ADDR_%X.w", c, decoded->params.immed); + } else { + return sprintf(dst, "%s $%X.w", c, decoded->params.immed); + } case MODE_ABSOLUTE: - return sprintf(dst, "%s $%X", c, decoded->params.immed); + if (labels) { + return sprintf(dst, "%s ADDR_%X.l", c, decoded->params.immed); + } else { + return sprintf(dst, "%s $%X", c, decoded->params.immed); + } case MODE_PC_DISPLACE: - return sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement); + if (labels) { + return sprintf(dst, "%s ADDR_%X(pc)", c, address + 2 + decoded->params.regs.displacement); + } else { + return sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement); + } case MODE_PC_INDEX_DISP8: return sprintf(dst, "%s (%d, pc, %c%d.%c)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w'); default: @@ -1191,7 +1203,7 @@ } } -int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma) +int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma, uint8_t labels, uint32_t address) { int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1; char *rtype, *last_rtype; @@ -1245,11 +1257,11 @@ } return oplen; } else { - return m68k_disasm_op(decoded, dst, need_comma); + return m68k_disasm_op(decoded, dst, need_comma, labels, address); } } -int m68k_disasm(m68kinst * decoded, char * dst) +int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels) { int ret,op1len; uint8_t size; @@ -1265,21 +1277,34 @@ strcpy(dst+ret, cond_mnem[decoded->extra.cond]); ret = strlen(dst); if (decoded->op != M68K_SCC) { - if (decoded->op == M68K_DBCC) { - ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); + if (labels) { + if (decoded->op == M68K_DBCC) { + ret += sprintf(dst+ret, " d%d, ADDR_%X", decoded->dst.params.regs.pri, decoded->address + 2 + decoded->src.params.immed); + } else { + ret += sprintf(dst+ret, " ADDR_%X", decoded->address + 2 + decoded->src.params.immed); + } } else { - ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); + if (decoded->op == M68K_DBCC) { + ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); + } else { + ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); + } } return ret; } break; case M68K_BSR: - ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); + if (labels) { + ret = sprintf(dst, "bsr%s ADDR_%X", decoded->variant == VAR_BYTE ? ".s" : "", + decoded->address + 2 + decoded->src.params.immed); + } else { + ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); + } return ret; case M68K_MOVE_FROM_SR: ret = sprintf(dst, "%s", mnemonics[decoded->op]); ret += sprintf(dst + ret, " SR"); - ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1); + ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1, labels, decoded->address); return ret; case M68K_ANDI_SR: case M68K_EORI_SR: @@ -1291,17 +1316,17 @@ case M68K_MOVE_CCR: case M68K_ORI_CCR: ret = sprintf(dst, "%s", mnemonics[decoded->op]); - ret += m68k_disasm_op(&(decoded->src), dst + ret, 0); + ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address); ret += sprintf(dst + ret, ", %s", special_op); return ret; case M68K_MOVE_USP: ret = sprintf(dst, "%s", mnemonics[decoded->op]); if (decoded->src.addr_mode != MODE_UNUSED) { - ret += m68k_disasm_op(&(decoded->src), dst + ret, 0); + ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address); ret += sprintf(dst + ret, ", USP"); } else { ret += sprintf(dst + ret, "USP, "); - ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0); + ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address); } return ret; default: @@ -1312,14 +1337,23 @@ size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : ""))); } if (decoded->op == M68K_MOVEM) { - op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0); + op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0, labels, decoded->address); ret += op1len; - ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len); + ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len, labels, decoded->address); } else { - op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0); + op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address); ret += op1len; - ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len); + ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len, labels, decoded->address); } return ret; } +int m68k_disasm(m68kinst * decoded, char * dst) +{ + return m68k_disasm_ex(decoded, dst, 0); +} + +int m68k_disasm_labels(m68kinst * decoded, char * dst) +{ + return m68k_disasm_ex(decoded, dst, 1); +} diff -r c4d10c2aaee2 -r ab50421b1b7a 68kinst.h --- a/68kinst.h Sun Dec 30 09:55:07 2012 -0800 +++ b/68kinst.h Sun Dec 30 09:55:18 2012 -0800 @@ -185,6 +185,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * dst, uint32_t address); uint32_t m68k_cycles(m68kinst * inst); int m68k_disasm(m68kinst * decoded, char * dst); +int m68k_disasm_labels(m68kinst * decoded, char * dst); #endif diff -r c4d10c2aaee2 -r ab50421b1b7a dis.c --- a/dis.c Sun Dec 30 09:55:07 2012 -0800 +++ b/dis.c Sun Dec 30 09:55:18 2012 -0800 @@ -3,6 +3,7 @@ #include uint8_t visited[(16*1024*1024)/16]; +uint8_t label[(16*1024*1024)/16]; void visit(uint32_t address) { @@ -10,12 +11,25 @@ visited[address/16] |= 1 << ((address / 2) % 8); } +void reference(uint32_t address) +{ + address &= 0xFFFFFF; + //printf("referenced: %X\n", address); + label[address/16] |= 1 << ((address / 2) % 8); +} + uint8_t is_visited(uint32_t address) { address &= 0xFFFFFF; return visited[address/16] & (1 << ((address / 2) % 8)); } +uint8_t is_label(uint32_t address) +{ + address &= 0xFFFFFF; + return label[address/16] & (1 << ((address / 2) % 8)); +} + typedef struct deferred { uint32_t address; struct deferred *next; @@ -33,7 +47,22 @@ return d; } -#define SIMPLE 0 +void check_reference(m68kinst * inst, m68k_op_info * op) +{ + switch(op->addr_mode) + { + case MODE_PC_DISPLACE: + reference(inst->address + 2 + op->params.regs.displacement); + break; + case MODE_ABSOLUTE: + case MODE_ABSOLUTE_SHORT: + reference(op->params.immed); + break; + } +} + +uint8_t labels = 0; +uint8_t addr = 0; int main(int argc, char ** argv) { @@ -49,12 +78,24 @@ filebuf = malloc(filesize); fread(filebuf, 2, filesize/2, f); fclose(f); + for(uint8_t opt = 2; opt < argc; ++opt) { + if (argv[opt][0] == '-') { + switch (argv[opt][1]) + { + case 'l': + labels = 1; + break; + case 'a': + addr = 1; + break; + } + } + } for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) { *cur = (*cur >> 8) | (*cur << 8); } uint32_t address = filebuf[2] << 16 | filebuf[3], tmp_addr; - #if !SIMPLE uint16_t *encoded, *next; uint32_t size; deferred *def = NULL, *tmpd; @@ -86,17 +127,21 @@ encoded = next; //m68k_disasm(&instbuf, disbuf); //printf("%X: %s\n", instbuf.address, disbuf); + check_reference(&instbuf, &(instbuf.src)); + check_reference(&instbuf, &(instbuf.dst)); if (instbuf.op == M68K_ILLEGAL || instbuf.op == M68K_RTS || instbuf.op == M68K_RTE) { break; } else if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) { if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) { address = instbuf.address + 2 + instbuf.src.params.immed; encoded = filebuf + address/2; + reference(address); if (is_visited(address)) { break; } } else { tmp_addr = instbuf.address + 2 + instbuf.src.params.immed; + reference(tmp_addr); def = defer(tmp_addr, def); } } else if(instbuf.op == M68K_JMP) { @@ -124,22 +169,33 @@ } } } + if (labels) { + for (address = filesize; address < (16*1024*1024); address++) { + if (is_label(address)) { + printf("ADR_%X equ $%X\n", address, address); + } + } + puts(""); + } for (address = 0; address < filesize; address+=2) { if (is_visited(address)) { encoded = filebuf + address/2; m68k_decode(encoded, &instbuf, address); - m68k_disasm(&instbuf, disbuf); - printf("%X: %s\n", instbuf.address, disbuf); + if (labels) { + m68k_disasm_labels(&instbuf, disbuf); + if (is_label(instbuf.address)) { + printf("ADR_%X:\n", instbuf.address); + } + if (addr) { + printf("\t%s\t;%X\n", disbuf, instbuf.address); + } else { + printf("\t%s\n", disbuf); + } + } else { + m68k_disasm(&instbuf, disbuf); + printf("%X: %s\n", instbuf.address, disbuf); + } } } - #else - for(cur = filebuf + 0x100; (cur - filebuf) < (filesize/2); ) - { - unsigned short * start = cur; - cur = m68k_decode(cur, &instbuf, (start - filebuf)*2); - m68k_disasm(&instbuf, disbuf); - printf("%X: %s\n", instbuf.address, disbuf); - } - #endif return 0; }