Mercurial > repos > blastem
diff dis.c @ 134:ab50421b1b7a
Improve disassembler
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 30 Dec 2012 09:55:18 -0800 |
parents | e821b6fde0e4 |
children | cce22fb4c450 |
line wrap: on
line diff
--- 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 <stdlib.h> 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; }