comparison zdis.c @ 199:69585e7d474f

Add initial stab at Z80 decoder and disassembler
author Mike Pavone <pavone@retrodev.com>
date Sun, 20 Jan 2013 19:11:24 -0800
parents
children 852b8765bba6
comparison
equal deleted inserted replaced
198:209a37eed3e7 199:69585e7d474f
1 #include "z80inst.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 uint8_t visited[(64*1024)/8];
6 uint8_t label[(64*1024)/8];
7
8 void visit(uint16_t address)
9 {
10 visited[address/8] |= 1 << (address % 8);
11 }
12
13 void reference(uint16_t address)
14 {
15 //printf("referenced: %X\n", address);
16 label[address/8] |= 1 << (address % 8);
17 }
18
19 uint8_t is_visited(uint16_t address)
20 {
21 return visited[address/8] & (1 << (address % 8));
22 }
23
24 uint8_t is_label(uint16_t address)
25 {
26 return label[address/8] & (1 << (address % 8));
27 }
28
29 typedef struct deferred {
30 uint16_t address;
31 struct deferred *next;
32 } deferred;
33
34 deferred * defer(uint16_t address, deferred * next)
35 {
36 if (is_visited(address)) {
37 return next;
38 }
39 //printf("deferring %X\n", address);
40 deferred * d = malloc(sizeof(deferred));
41 d->address = address;
42 d->next = next;
43 return d;
44 }
45
46 uint8_t labels = 0;
47 uint8_t addr = 0;
48 uint8_t only = 0;
49
50 int main(int argc, char ** argv)
51 {
52 long filesize;
53 uint8_t *filebuf;
54 char disbuf[1024];
55 z80inst instbuf;
56 uint8_t * cur;
57 FILE * f = fopen(argv[1], "rb");
58 fseek(f, 0, SEEK_END);
59 filesize = ftell(f);
60 fseek(f, 0, SEEK_SET);
61 filebuf = malloc(filesize);
62 fread(filebuf, 1, filesize, f);
63 fclose(f);
64 deferred *def = NULL, *tmpd;
65 for(uint8_t opt = 2; opt < argc; ++opt) {
66 if (argv[opt][0] == '-') {
67 FILE * address_log;
68 switch (argv[opt][1])
69 {
70 case 'l':
71 labels = 1;
72 break;
73 case 'a':
74 addr = 1;
75 break;
76 case 'o':
77 only = 1;
78 break;
79 case 'f':
80 opt++;
81 if (opt >= argc) {
82 fputs("-f must be followed by a filename\n", stderr);
83 exit(1);
84 }
85 address_log = fopen(argv[opt], "r");
86 if (!address_log) {
87 fprintf(stderr, "Failed to open %s for reading\n", argv[opt]);
88 exit(1);
89 }
90 while (fgets(disbuf, sizeof(disbuf), address_log)) {
91 if (disbuf[0]) {
92 uint16_t address = strtol(disbuf, NULL, 16);
93 if (address) {
94 def = defer(address, def);
95 reference(address);
96 }
97 }
98 }
99 }
100 } else {
101 uint16_t address = strtol(argv[opt], NULL, 16);
102 def = defer(address, def);
103 reference(address);
104 }
105 }
106 uint16_t start = 0;
107 uint8_t *encoded, *next;
108 uint32_t size;
109 if (!def || !only) {
110 def = defer(start, def);
111 }
112 uint16_t address;
113 while(def) {
114 do {
115 encoded = NULL;
116 address = def->address;
117 if (!is_visited(address)) {
118 encoded = filebuf + address;
119 }
120 tmpd = def;
121 def = def->next;
122 free(tmpd);
123 } while(def && encoded == NULL);
124 if (!encoded) {
125 break;
126 }
127 for(;;) {
128 if (address > filesize) {
129 break;
130 }
131 visit(address);
132 next = z80_decode(encoded, &instbuf);
133 address += (next-encoded);
134 encoded = next;
135
136 //m68k_disasm(&instbuf, disbuf);
137 //printf("%X: %s\n", instbuf.address, disbuf);
138 if (instbuf.op == Z80_HALT || instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_RST) {
139 break;
140 }
141 switch (instbuf.op)
142 {
143 case Z80_JR:
144 address += instbuf.immed;
145 encoded = filebuf + address;
146 break;
147 case Z80_JRCC:
148 reference(address + instbuf.immed);
149 def = defer(address + instbuf.immed, def);
150 break;
151 case Z80_JP:
152 address = instbuf.immed;
153 encoded = filebuf + address;
154 break;
155 case Z80_JPCC:
156 case Z80_CALL:
157 case Z80_CALLCC:
158 reference(instbuf.immed);
159 def = defer(instbuf.immed, def);
160 break;
161 }
162 }
163 }
164 if (labels) {
165 for (address = filesize; address < (64*1024); address++) {
166 if (is_label(address)) {
167 printf("ADR_%X equ $%X\n", address, address);
168 }
169 }
170 puts("");
171 }
172 for (address = 0; address < filesize; address++) {
173 if (is_visited(address)) {
174 encoded = filebuf + address;
175 z80_decode(encoded, &instbuf);
176 if (labels) {
177 /*m68k_disasm_labels(&instbuf, disbuf);
178 if (is_label(instbuf.address)) {
179 printf("ADR_%X:\n", instbuf.address);
180 }
181 if (addr) {
182 printf("\t%s\t;%X\n", disbuf, instbuf.address);
183 } else {
184 printf("\t%s\n", disbuf);
185 }*/
186 } else {
187 z80_disasm(&instbuf, disbuf);
188 printf("%X: %s\n", address, disbuf);
189 }
190 }
191 }
192 return 0;
193 }