# HG changeset patch # User Mike Pavone # Date 1355372231 28800 # Node ID ec71370820f2ad3214887b10e98b326be76c9450 # Parent 3fc57e1a2c56fd9cd457ac54f13ffcb18bdfb776 Add logic for following control flow based on logic in the translator diff -r 3fc57e1a2c56 -r ec71370820f2 dis.c --- a/dis.c Sun Dec 09 18:40:45 2012 -0800 +++ b/dis.c Wed Dec 12 20:17:11 2012 -0800 @@ -2,6 +2,38 @@ #include #include +uint8_t visited[(16*1024*1024)/16]; + +void visit(uint32_t address) +{ + address &= 0xFFFFFF; + visited[address/16] |= 1 << ((address / 2) % 8); +} + +uint8_t is_visited(uint32_t address) +{ + address &= 0xFFFFFF; + return visited[address/16] & (1 << ((address / 2) % 8)); +} + +typedef struct deferred { + uint32_t address; + struct deferred *next; +} deferred; + +deferred * defer(uint32_t address, deferred * next) +{ + if (is_visited(address)) { + return next; + } + deferred * d = malloc(sizeof(deferred)); + d->address = address; + d->next = next; + return d; +} + +#define SIMPLE 0 + int main(int argc, char ** argv) { long filesize; @@ -20,6 +52,74 @@ { *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; + def = defer(address, def); + def = defer(filebuf[0x68/2] << 16 | filebuf[0x6A/2], def); + def = defer(filebuf[0x70/2] << 16 | filebuf[0x72/2], def); + def = defer(filebuf[0x78/2] << 16 | filebuf[0x7A/2], def); + while(def) { + do { + encoded = NULL; + address = def->address; + if (!is_visited(address)) { + encoded = filebuf + address/2; + } + tmpd = def; + def = def->next; + free(tmpd); + } while(def && encoded == NULL); + if (!encoded) { + break; + } + for(;;) { + visit(instbuf.address); + next = m68k_decode(encoded, &instbuf, address); + address += (next-encoded)*2; + encoded = next; + m68k_disasm(&instbuf, disbuf); + 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; + if (is_visited(address)) { + break; + } + } else { + tmp_addr = instbuf.address + 2 + instbuf.src.params.immed; + def = defer(tmp_addr, def); + } + } else if(instbuf.op == M68K_JMP) { + if (instbuf.src.addr_mode == MODE_ABSOLUTE || MODE_ABSOLUTE_SHORT) { + address = instbuf.src.params.immed; + encoded = filebuf + address/2; + if (is_visited(address)) { + break; + } + } else { + break; + } + } else if(instbuf.op == M68K_JSR) { + if (instbuf.src.addr_mode == MODE_ABSOLUTE || MODE_ABSOLUTE_SHORT) { + def = defer(instbuf.src.params.immed, def); + } + } + } + } + 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); + } + } + #else for(cur = filebuf + 0x100; (cur - filebuf) < (filesize/2); ) { //printf("cur: %p: %x\n", cur, *cur); @@ -28,5 +128,6 @@ m68k_disasm(&instbuf, disbuf); printf("%X: %s\n", instbuf.address, disbuf); } + #endif return 0; }