Mercurial > repos > blastem
comparison dis.c @ 744:fc68992cf18d
Merge windows branch with latest changes
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 May 2015 21:19:55 -0700 |
parents | 1a14f5f6c6a1 |
children | 3eced113081c |
comparison
equal
deleted
inserted
replaced
743:cf78cb045fa4 | 744:fc68992cf18d |
---|---|
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "68kinst.h" | 6 #include "68kinst.h" |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string.h> | |
10 #include "vos_program_module.h" | |
11 #include "tern.h" | |
9 | 12 |
10 uint8_t visited[(16*1024*1024)/16]; | 13 uint8_t visited[(16*1024*1024)/16]; |
11 uint8_t label[(16*1024*1024)/8]; | 14 uint16_t label[(16*1024*1024)/8]; |
12 | 15 |
13 void visit(uint32_t address) | 16 void visit(uint32_t address) |
14 { | 17 { |
15 address &= 0xFFFFFF; | 18 address &= 0xFFFFFF; |
16 visited[address/16] |= 1 << ((address / 2) % 8); | 19 visited[address/16] |= 1 << ((address / 2) % 8); |
18 | 21 |
19 void reference(uint32_t address) | 22 void reference(uint32_t address) |
20 { | 23 { |
21 address &= 0xFFFFFF; | 24 address &= 0xFFFFFF; |
22 //printf("referenced: %X\n", address); | 25 //printf("referenced: %X\n", address); |
23 label[address/16] |= 1 << (address % 8); | 26 label[address/16] |= 1 << (address % 16); |
24 } | 27 } |
25 | 28 |
26 uint8_t is_visited(uint32_t address) | 29 uint8_t is_visited(uint32_t address) |
27 { | 30 { |
28 address &= 0xFFFFFF; | 31 address &= 0xFFFFFF; |
29 return visited[address/16] & (1 << ((address / 2) % 8)); | 32 return visited[address/16] & (1 << ((address / 2) % 8)); |
30 } | 33 } |
31 | 34 |
32 uint8_t is_label(uint32_t address) | 35 uint16_t is_label(uint32_t address) |
33 { | 36 { |
34 address &= 0xFFFFFF; | 37 address &= 0xFFFFFF; |
35 return label[address/16] & (1 << (address % 8)); | 38 return label[address/16] & (1 << (address % 16)); |
39 } | |
40 | |
41 typedef struct { | |
42 uint32_t num_labels; | |
43 uint32_t storage; | |
44 char *labels[]; | |
45 } label_names; | |
46 | |
47 tern_node * add_label(tern_node * head, char * name, uint32_t address) | |
48 { | |
49 char key[MAX_INT_KEY_SIZE]; | |
50 address &= 0xFFFFFF; | |
51 reference(address); | |
52 tern_int_key(address, key); | |
53 label_names * names = tern_find_ptr(head, key); | |
54 if (names) | |
55 { | |
56 if (names->num_labels == names->storage) | |
57 { | |
58 names->storage = names->storage + (names->storage >> 1); | |
59 names = realloc(names, sizeof(label_names) + names->storage * sizeof(char *)); | |
60 } | |
61 } else { | |
62 names = malloc(sizeof(label_names) + 4 * sizeof(char *)); | |
63 names->num_labels = 0; | |
64 names->storage = 4; | |
65 head = tern_insert_ptr(head, key, names); | |
66 } | |
67 names->labels[names->num_labels++] = strdup(name); | |
68 return head; | |
36 } | 69 } |
37 | 70 |
38 typedef struct deferred { | 71 typedef struct deferred { |
39 uint32_t address; | 72 uint32_t address; |
40 struct deferred *next; | 73 struct deferred *next; |
41 } deferred; | 74 } deferred; |
42 | 75 |
43 deferred * defer(uint32_t address, deferred * next) | 76 deferred * defer(uint32_t address, deferred * next) |
44 { | 77 { |
45 if (is_visited(address)) { | 78 if (is_visited(address) || address & 1) { |
46 return next; | 79 return next; |
47 } | 80 } |
48 //printf("deferring %X\n", address); | 81 //printf("deferring %X\n", address); |
49 deferred * d = malloc(sizeof(deferred)); | 82 deferred * d = malloc(sizeof(deferred)); |
50 d->address = address; | 83 d->address = address; |
64 reference(op->params.immed); | 97 reference(op->params.immed); |
65 break; | 98 break; |
66 } | 99 } |
67 } | 100 } |
68 | 101 |
69 uint8_t labels = 0; | 102 int label_fun(char *dst, uint32_t address, void * data) |
70 uint8_t addr = 0; | 103 { |
71 uint8_t only = 0; | 104 tern_node * labels = data; |
105 char key[MAX_INT_KEY_SIZE]; | |
106 label_names * names = tern_find_ptr(labels, tern_int_key(address & 0xFFFFFF, key)); | |
107 if (names) | |
108 { | |
109 return sprintf(dst, "%s", names->labels[0]); | |
110 } else { | |
111 return m68k_default_label_fun(dst, address, NULL); | |
112 } | |
113 } | |
72 | 114 |
73 int main(int argc, char ** argv) | 115 int main(int argc, char ** argv) |
74 { | 116 { |
75 long filesize; | 117 long filesize; |
76 unsigned short *filebuf; | 118 unsigned short *filebuf; |
77 char disbuf[1024]; | 119 char disbuf[1024]; |
78 m68kinst instbuf; | 120 m68kinst instbuf; |
79 unsigned short * cur; | 121 unsigned short * cur; |
80 FILE * f = fopen(argv[1], "rb"); | |
81 fseek(f, 0, SEEK_END); | |
82 filesize = ftell(f); | |
83 fseek(f, 0, SEEK_SET); | |
84 filebuf = malloc(filesize); | |
85 fread(filebuf, 2, filesize/2, f); | |
86 fclose(f); | |
87 deferred *def = NULL, *tmpd; | 122 deferred *def = NULL, *tmpd; |
123 | |
124 uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0; | |
125 | |
88 for(uint8_t opt = 2; opt < argc; ++opt) { | 126 for(uint8_t opt = 2; opt < argc; ++opt) { |
89 if (argv[opt][0] == '-') { | 127 if (argv[opt][0] == '-') { |
90 FILE * address_log; | 128 FILE * address_log; |
91 switch (argv[opt][1]) | 129 switch (argv[opt][1]) |
92 { | 130 { |
97 addr = 1; | 135 addr = 1; |
98 break; | 136 break; |
99 case 'o': | 137 case 'o': |
100 only = 1; | 138 only = 1; |
101 break; | 139 break; |
140 case 'v': | |
141 vos = 1; | |
142 break; | |
143 case 'r': | |
144 reset = 1; | |
145 break; | |
102 case 'f': | 146 case 'f': |
103 opt++; | 147 opt++; |
104 if (opt >= argc) { | 148 if (opt >= argc) { |
105 fputs("-f must be followed by a filename\n", stderr); | 149 fputs("-f must be followed by a filename\n", stderr); |
106 exit(1); | 150 exit(1); |
124 uint32_t address = strtol(argv[opt], NULL, 16); | 168 uint32_t address = strtol(argv[opt], NULL, 16); |
125 def = defer(address, def); | 169 def = defer(address, def); |
126 reference(address); | 170 reference(address); |
127 } | 171 } |
128 } | 172 } |
129 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) | 173 |
174 FILE * f = fopen(argv[1], "rb"); | |
175 fseek(f, 0, SEEK_END); | |
176 filesize = ftell(f); | |
177 fseek(f, 0, SEEK_SET); | |
178 | |
179 tern_node * named_labels = NULL; | |
180 char int_key[MAX_INT_KEY_SIZE]; | |
181 uint32_t address_off, address_end; | |
182 if (vos) | |
130 { | 183 { |
131 *cur = (*cur >> 8) | (*cur << 8); | 184 vos_program_module header; |
132 } | 185 vos_read_header(f, &header); |
133 uint32_t start = filebuf[2] << 16 | filebuf[3], tmp_addr; | 186 vos_read_alloc_module_map(f, &header); |
134 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; | 187 address_off = header.user_boundary; |
135 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; | 188 address_end = address_off + filesize - 0x1000; |
136 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; | 189 def = defer(header.main_entry_link.code_address, def); |
190 named_labels = add_label(named_labels, "main_entry_link", header.main_entry_link.code_address); | |
191 for (int i = 0; i < header.n_modules; i++) | |
192 { | |
193 if (!reset || header.module_map_entries[i].code_address != header.user_boundary) | |
194 { | |
195 def = defer(header.module_map_entries[i].code_address, def); | |
196 } | |
197 named_labels = add_label(named_labels, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address); | |
198 } | |
199 fseek(f, 0x1000, SEEK_SET); | |
200 filebuf = malloc(filesize - 0x1000); | |
201 if (fread(filebuf, 2, (filesize - 0x1000)/2, f) != (filesize - 0x1000)/2) | |
202 { | |
203 fprintf(stderr, "Failure while reading file %s\n", argv[1]); | |
204 } | |
205 fclose(f); | |
206 for(cur = filebuf; cur - filebuf < ((filesize - 0x1000)/2); ++cur) | |
207 { | |
208 *cur = (*cur >> 8) | (*cur << 8); | |
209 } | |
210 if (reset) | |
211 { | |
212 def = defer(filebuf[2] << 16 | filebuf[3], def); | |
213 named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]); | |
214 } | |
215 } else { | |
216 address_off = 0; | |
217 address_end = filesize; | |
218 filebuf = malloc(filesize); | |
219 if (fread(filebuf, 2, filesize/2, f) != filesize/2) | |
220 { | |
221 fprintf(stderr, "Failure while reading file %s\n", argv[1]); | |
222 } | |
223 fclose(f); | |
224 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) | |
225 { | |
226 *cur = (*cur >> 8) | (*cur << 8); | |
227 } | |
228 uint32_t start = filebuf[2] << 16 | filebuf[3]; | |
229 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; | |
230 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; | |
231 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; | |
232 named_labels = add_label(named_labels, "start", start); | |
233 named_labels = add_label(named_labels, "int_2", int_2); | |
234 named_labels = add_label(named_labels, "int_4", int_4); | |
235 named_labels = add_label(named_labels, "int_6", int_6); | |
236 if (!def || !only) { | |
237 def = defer(start, def); | |
238 def = defer(int_2, def); | |
239 def = defer(int_4, def); | |
240 def = defer(int_6, def); | |
241 } | |
242 } | |
137 uint16_t *encoded, *next; | 243 uint16_t *encoded, *next; |
138 uint32_t size; | 244 uint32_t size, tmp_addr; |
139 if (!def || !only) { | |
140 def = defer(start, def); | |
141 def = defer(int_2, def); | |
142 def = defer(int_4, def); | |
143 def = defer(int_6, def); | |
144 } | |
145 uint32_t address; | 245 uint32_t address; |
146 while(def) { | 246 while(def) { |
147 do { | 247 do { |
148 encoded = NULL; | 248 encoded = NULL; |
149 address = def->address; | 249 address = def->address; |
150 if (!is_visited(address)) { | 250 if (!is_visited(address)) { |
151 encoded = filebuf + address/2; | 251 encoded = filebuf + (address - address_off)/2; |
152 } | 252 } |
153 tmpd = def; | 253 tmpd = def; |
154 def = def->next; | 254 def = def->next; |
155 free(tmpd); | 255 free(tmpd); |
156 } while(def && encoded == NULL); | 256 } while(def && encoded == NULL); |
157 if (!encoded) { | 257 if (!encoded) { |
158 break; | 258 break; |
159 } | 259 } |
160 for(;;) { | 260 for(;;) { |
161 if (address > filesize) { | 261 if (address > address_end || address < address_off) { |
162 break; | 262 break; |
163 } | 263 } |
164 visit(address); | 264 visit(address); |
165 next = m68k_decode(encoded, &instbuf, address); | 265 next = m68k_decode(encoded, &instbuf, address); |
166 address += (next-encoded)*2; | 266 address += (next-encoded)*2; |
173 break; | 273 break; |
174 } | 274 } |
175 if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) { | 275 if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) { |
176 if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) { | 276 if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) { |
177 address = instbuf.address + 2 + instbuf.src.params.immed; | 277 address = instbuf.address + 2 + instbuf.src.params.immed; |
178 encoded = filebuf + address/2; | 278 encoded = filebuf + (address - address_off)/2; |
179 reference(address); | 279 reference(address); |
180 if (is_visited(address)) { | 280 if (is_visited(address)) { |
181 break; | 281 break; |
182 } | 282 } |
183 } else { | 283 } else { |
186 def = defer(tmp_addr, def); | 286 def = defer(tmp_addr, def); |
187 } | 287 } |
188 } else if(instbuf.op == M68K_JMP) { | 288 } else if(instbuf.op == M68K_JMP) { |
189 if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { | 289 if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { |
190 address = instbuf.src.params.immed; | 290 address = instbuf.src.params.immed; |
191 encoded = filebuf + address/2; | 291 encoded = filebuf + (address - address_off)/2; |
192 if (is_visited(address)) { | 292 if (is_visited(address)) { |
193 break; | 293 break; |
194 } | 294 } |
195 } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { | 295 } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { |
196 address = instbuf.src.params.regs.displacement + instbuf.address + 2; | 296 address = instbuf.src.params.regs.displacement + instbuf.address + 2; |
197 encoded = filebuf + address/2; | 297 encoded = filebuf + (address - address_off)/2; |
198 if (is_visited(address)) { | 298 if (is_visited(address)) { |
199 break; | 299 break; |
200 } | 300 } |
201 } else { | 301 } else { |
202 break; | 302 break; |
209 } | 309 } |
210 } | 310 } |
211 } | 311 } |
212 } | 312 } |
213 if (labels) { | 313 if (labels) { |
214 for (address = filesize; address < (16*1024*1024); address++) { | 314 for (address = 0; address < address_off; address++) { |
215 if (is_label(address)) { | 315 if (is_label(address)) { |
216 printf("ADR_%X equ $%X\n", address, address); | 316 printf("ADR_%X equ $%X\n", address, address); |
217 } | 317 } |
218 } | 318 } |
319 for (address = filesize; address < (16*1024*1024); address++) { | |
320 char key[MAX_INT_KEY_SIZE]; | |
321 tern_int_key(address, key); | |
322 label_names *names = tern_find_ptr(named_labels, key); | |
323 if (names) { | |
324 for (int i = 0; i < names->num_labels; i++) | |
325 { | |
326 printf("%s equ $%X\n", names->labels[i], address); | |
327 } | |
328 } else if (is_label(address)) { | |
329 printf("ADR_%X equ $%X\n", address, address); | |
330 } | |
331 } | |
219 puts(""); | 332 puts(""); |
220 } | 333 } |
221 for (address = 0; address < filesize; address+=2) { | 334 for (address = address_off; address < address_end; address+=2) { |
222 if (is_visited(address)) { | 335 if (is_visited(address)) { |
223 encoded = filebuf + address/2; | 336 encoded = filebuf + (address-address_off)/2; |
224 m68k_decode(encoded, &instbuf, address); | 337 m68k_decode(encoded, &instbuf, address); |
225 if (labels) { | 338 if (labels) { |
226 m68k_disasm_labels(&instbuf, disbuf); | 339 m68k_disasm_labels(&instbuf, disbuf, label_fun, named_labels); |
227 if (address == start) { | 340 char keybuf[MAX_INT_KEY_SIZE]; |
228 puts("start:"); | 341 label_names * names = tern_find_ptr(named_labels, tern_int_key(address, keybuf)); |
229 } | 342 if (names) |
230 if(address == int_2) { | 343 { |
231 puts("int_2:"); | 344 for (int i = 0; i < names->num_labels; i++) |
232 } | 345 { |
233 if(address == int_4) { | 346 printf("%s:\n", names->labels[i]); |
234 puts("int_4:"); | 347 } |
235 } | 348 } else if (is_label(instbuf.address)) { |
236 if(address == int_6) { | |
237 puts("int_6:"); | |
238 } | |
239 if (is_label(instbuf.address)) { | |
240 printf("ADR_%X:\n", instbuf.address); | 349 printf("ADR_%X:\n", instbuf.address); |
241 } | 350 } |
242 if (addr) { | 351 if (addr) { |
243 printf("\t%s\t;%X\n", disbuf, instbuf.address); | 352 printf("\t%s\t;%X\n", disbuf, instbuf.address); |
244 } else { | 353 } else { |