Mercurial > repos > blastem
view zdis.c @ 298:170722e80fc0
Fix handling of instructions that combine an IX/IY displacement with another prefix in test generator
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 08 May 2013 22:45:29 -0700 |
parents | 852b8765bba6 |
children | a13329645ea3 |
line wrap: on
line source
#include "z80inst.h" #include <stdio.h> #include <stdlib.h> uint8_t visited[(64*1024)/8]; uint8_t label[(64*1024)/8]; void visit(uint16_t address) { visited[address/8] |= 1 << (address % 8); } void reference(uint16_t address) { //printf("referenced: %X\n", address); label[address/8] |= 1 << (address % 8); } uint8_t is_visited(uint16_t address) { return visited[address/8] & (1 << (address % 8)); } uint8_t is_label(uint16_t address) { return label[address/8] & (1 << (address % 8)); } typedef struct deferred { uint16_t address; struct deferred *next; } deferred; deferred * defer(uint16_t address, deferred * next) { if (is_visited(address)) { return next; } //printf("deferring %X\n", address); deferred * d = malloc(sizeof(deferred)); d->address = address; d->next = next; return d; } uint8_t labels = 0; uint8_t addr = 0; uint8_t only = 0; int main(int argc, char ** argv) { long filesize; uint8_t *filebuf; char disbuf[1024]; z80inst instbuf; uint8_t * cur; FILE * f = fopen(argv[1], "rb"); fseek(f, 0, SEEK_END); filesize = ftell(f); fseek(f, 0, SEEK_SET); filebuf = malloc(filesize); fread(filebuf, 1, filesize, f); fclose(f); deferred *def = NULL, *tmpd; for(uint8_t opt = 2; opt < argc; ++opt) { if (argv[opt][0] == '-') { FILE * address_log; switch (argv[opt][1]) { case 'l': labels = 1; break; case 'a': addr = 1; break; case 'o': only = 1; break; case 'f': opt++; if (opt >= argc) { fputs("-f must be followed by a filename\n", stderr); exit(1); } address_log = fopen(argv[opt], "r"); if (!address_log) { fprintf(stderr, "Failed to open %s for reading\n", argv[opt]); exit(1); } while (fgets(disbuf, sizeof(disbuf), address_log)) { if (disbuf[0]) { uint16_t address = strtol(disbuf, NULL, 16); if (address) { def = defer(address, def); reference(address); } } } } } else { uint16_t address = strtol(argv[opt], NULL, 16); def = defer(address, def); reference(address); } } uint16_t start = 0; uint8_t *encoded, *next; uint32_t size; if (!def || !only) { def = defer(start, def); } uint16_t address; while(def) { do { encoded = NULL; address = def->address; if (!is_visited(address)) { encoded = filebuf + address; } tmpd = def; def = def->next; free(tmpd); } while(def && encoded == NULL); if (!encoded) { break; } for(;;) { if (address > filesize || is_visited(address)) { break; } visit(address); next = z80_decode(encoded, &instbuf); address += (next-encoded); encoded = next; //z80_disasm(&instbuf, disbuf); //printf("%X: %s\n", address, disbuf); if (instbuf.op == Z80_HALT || instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_RST) { break; } switch (instbuf.op) { case Z80_JR: address += instbuf.immed; encoded = filebuf + address; break; case Z80_JRCC: reference(address + instbuf.immed); def = defer(address + instbuf.immed, def); break; case Z80_JP: address = instbuf.immed; encoded = filebuf + address; break; case Z80_JPCC: case Z80_CALL: case Z80_CALLCC: reference(instbuf.immed); def = defer(instbuf.immed, def); break; } } } if (labels) { for (address = filesize; address < (64*1024); address++) { if (is_label(address)) { printf("ADR_%X equ $%X\n", address, address); } } puts(""); } for (address = 0; address < filesize; address++) { if (is_visited(address)) { encoded = filebuf + address; z80_decode(encoded, &instbuf); 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 { z80_disasm(&instbuf, disbuf); printf("%X: %s\n", address, disbuf); } } } return 0; }