Mercurial > repos > blastem
comparison dis.c @ 2206:4c265d2f6c88
Minor refactor of 68K disassembler
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 27 Aug 2022 17:07:57 -0700 |
parents | 0c0d4233d826 |
children | 53411df7fc71 |
comparison
equal
deleted
inserted
replaced
2205:90297f1fb3fe | 2206:4c265d2f6c88 |
---|---|
10 #include <stdarg.h> | 10 #include <stdarg.h> |
11 #include <ctype.h> | 11 #include <ctype.h> |
12 #include "vos_program_module.h" | 12 #include "vos_program_module.h" |
13 #include "tern.h" | 13 #include "tern.h" |
14 #include "util.h" | 14 #include "util.h" |
15 | 15 #include "disasm.h" |
16 uint8_t visited[(16*1024*1024)/16]; | 16 |
17 uint16_t label[(16*1024*1024)/8]; | 17 int headless; |
18 | 18 void render_errorbox(char *title, char *message) {} |
19 void fatal_error(char *format, ...) | 19 void render_warnbox(char *title, char *message) {} |
20 { | 20 void render_infobox(char *title, char *message) {} |
21 va_list args; | 21 |
22 va_start(args, format); | 22 void check_reference(disasm_context *context, m68kinst * inst, m68k_op_info * op) |
23 vfprintf(stderr, format, args); | |
24 va_end(args); | |
25 exit(1); | |
26 } | |
27 | |
28 | |
29 void visit(uint32_t address) | |
30 { | |
31 address &= 0xFFFFFF; | |
32 visited[address/16] |= 1 << ((address / 2) % 8); | |
33 } | |
34 | |
35 void reference(uint32_t address) | |
36 { | |
37 address &= 0xFFFFFF; | |
38 //printf("referenced: %X\n", address); | |
39 label[address/16] |= 1 << (address % 16); | |
40 } | |
41 | |
42 uint8_t is_visited(uint32_t address) | |
43 { | |
44 address &= 0xFFFFFF; | |
45 return visited[address/16] & (1 << ((address / 2) % 8)); | |
46 } | |
47 | |
48 uint16_t is_label(uint32_t address) | |
49 { | |
50 address &= 0xFFFFFF; | |
51 return label[address/16] & (1 << (address % 16)); | |
52 } | |
53 | |
54 typedef struct { | |
55 uint32_t num_labels; | |
56 uint32_t storage; | |
57 uint32_t full_address; | |
58 char *labels[]; | |
59 } label_names; | |
60 | |
61 tern_node * weak_label(tern_node * head, const char *name, uint32_t address) | |
62 { | |
63 char key[MAX_INT_KEY_SIZE]; | |
64 tern_int_key(address & 0xFFFFFF, key); | |
65 label_names * names = tern_find_ptr(head, key); | |
66 if (names) | |
67 { | |
68 if (names->num_labels == names->storage) | |
69 { | |
70 names->storage = names->storage + (names->storage >> 1); | |
71 names = realloc(names, sizeof(label_names) + names->storage * sizeof(char *)); | |
72 } | |
73 } else { | |
74 names = malloc(sizeof(label_names) + 4 * sizeof(char *)); | |
75 names->num_labels = 0; | |
76 names->storage = 4; | |
77 head = tern_insert_ptr(head, key, names); | |
78 } | |
79 names->labels[names->num_labels++] = strdup(name); | |
80 names->full_address = address; | |
81 return head; | |
82 } | |
83 tern_node *add_label(tern_node * head, const char *name, uint32_t address) | |
84 { | |
85 reference(address); | |
86 return weak_label(head, name, address); | |
87 } | |
88 | |
89 typedef struct deferred { | |
90 uint32_t address; | |
91 struct deferred *next; | |
92 } deferred; | |
93 | |
94 deferred * defer(uint32_t address, deferred * next) | |
95 { | |
96 if (is_visited(address) || address & 1) { | |
97 return next; | |
98 } | |
99 //printf("deferring %X\n", address); | |
100 deferred * d = malloc(sizeof(deferred)); | |
101 d->address = address; | |
102 d->next = next; | |
103 return d; | |
104 } | |
105 | |
106 void check_reference(m68kinst * inst, m68k_op_info * op) | |
107 { | 23 { |
108 switch(op->addr_mode) | 24 switch(op->addr_mode) |
109 { | 25 { |
110 case MODE_PC_DISPLACE: | 26 case MODE_PC_DISPLACE: |
111 reference(inst->address + 2 + op->params.regs.displacement); | 27 reference(context, inst->address + 2 + op->params.regs.displacement); |
112 break; | 28 break; |
113 case MODE_ABSOLUTE: | 29 case MODE_ABSOLUTE: |
114 case MODE_ABSOLUTE_SHORT: | 30 case MODE_ABSOLUTE_SHORT: |
115 reference(op->params.immed); | 31 reference(context, op->params.immed); |
116 break; | 32 break; |
117 } | 33 } |
118 } | 34 } |
119 | 35 |
120 int label_fun(char *dst, uint32_t address, void * data) | 36 int label_fun(char *dst, uint32_t address, void * data) |
121 { | 37 { |
122 tern_node * labels = data; | 38 disasm_context *context = data; |
123 char key[MAX_INT_KEY_SIZE]; | 39 label_def *def = find_label(context, address); |
124 label_names * names = tern_find_ptr(labels, tern_int_key(address & 0xFFFFFF, key)); | 40 if (def && def->num_labels) { |
125 if (names) | 41 return sprintf(dst, "%s", def->labels[0]); |
126 { | 42 } |
127 return sprintf(dst, "%s", names->labels[0]); | 43 return m68k_default_label_fun(dst, address, NULL); |
128 } else { | |
129 return m68k_default_label_fun(dst, address, NULL); | |
130 } | |
131 } | |
132 | |
133 char * strip_ws(char * text) | |
134 { | |
135 while (*text && (!isprint(*text) || isblank(*text))) | |
136 { | |
137 text++; | |
138 } | |
139 char * ret = text; | |
140 text = ret + strlen(ret) - 1; | |
141 while (text > ret && (!isprint(*text) || isblank(*text))) | |
142 { | |
143 *text = 0; | |
144 text--; | |
145 } | |
146 return ret; | |
147 } | 44 } |
148 | 45 |
149 typedef struct { | 46 typedef struct { |
150 uint32_t address_off; | 47 uint32_t address_off; |
151 uint32_t address_end; | 48 uint32_t address_end; |
157 rom_def *rom = data; | 54 rom_def *rom = data; |
158 if (address >= rom->address_off && address < rom->address_end) { | 55 if (address >= rom->address_off && address < rom->address_end) { |
159 return rom->buffer[((address & 0xFFFFFF) - rom->address_off) >> 1]; | 56 return rom->buffer[((address & 0xFFFFFF) - rom->address_off) >> 1]; |
160 } | 57 } |
161 return 0; | 58 return 0; |
59 } | |
60 | |
61 void print_label_def(char *key, tern_val val, uint8_t valtype, void *data) | |
62 { | |
63 rom_def *rom = data; | |
64 label_def *label = val.ptrval; | |
65 uint32_t address = label->full_address & 0xFFFFFFF; | |
66 if (address >= rom->address_off && address < rom->address_end) { | |
67 return; | |
68 } | |
69 if (!label->referenced) { | |
70 return; | |
71 } | |
72 if (label->num_labels) { | |
73 for (int i = 0; i < label->num_labels; i++) | |
74 { | |
75 printf("%s equ $%X\n", label->labels[i], label->full_address); | |
76 } | |
77 } else { | |
78 printf("ADR_%X equ $%X\n", label->full_address, label->full_address); | |
79 } | |
162 } | 80 } |
163 | 81 |
164 int main(int argc, char ** argv) | 82 int main(int argc, char ** argv) |
165 { | 83 { |
166 long filesize; | 84 long filesize; |
167 unsigned short *filebuf = NULL; | 85 unsigned short *filebuf = NULL; |
168 char disbuf[1024]; | 86 char disbuf[1024]; |
169 m68kinst instbuf; | 87 m68kinst instbuf; |
170 unsigned short * cur; | 88 unsigned short * cur; |
171 deferred *def = NULL, *tmpd; | |
172 | 89 |
173 uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0; | 90 uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0; |
174 tern_node * named_labels = NULL; | 91 disasm_context *context = create_68000_disasm(); |
92 | |
175 | 93 |
176 uint32_t address_off = 0, address_end; | 94 uint32_t address_off = 0, address_end; |
177 uint8_t do_cd_labels = 0, main_cpu = 0; | 95 uint8_t do_cd_labels = 0, main_cpu = 0; |
178 for(uint8_t opt = 2; opt < argc; ++opt) { | 96 for(uint8_t opt = 2; opt < argc; ++opt) { |
179 if (argv[opt][0] == '-') { | 97 if (argv[opt][0] == '-') { |
223 while (fgets(disbuf, sizeof(disbuf), address_log)) { | 141 while (fgets(disbuf, sizeof(disbuf), address_log)) { |
224 if (disbuf[0]) { | 142 if (disbuf[0]) { |
225 char *end; | 143 char *end; |
226 uint32_t address = strtol(disbuf, &end, 16); | 144 uint32_t address = strtol(disbuf, &end, 16); |
227 if (address) { | 145 if (address) { |
228 def = defer(address, def); | 146 defer_disasm(context, address); |
229 reference(address); | |
230 if (*end == '=') { | 147 if (*end == '=') { |
231 named_labels = add_label(named_labels, strip_ws(end+1), address); | 148 add_label(context, strip_ws(end+1), address); |
149 } else { | |
150 reference(context, address); | |
232 } | 151 } |
233 } | 152 } |
234 } | 153 } |
235 } | 154 } |
236 fclose(address_log); | 155 fclose(address_log); |
237 } | 156 } |
238 } else { | 157 } else { |
239 char *end; | 158 char *end; |
240 uint32_t address = strtol(argv[opt], &end, 16); | 159 uint32_t address = strtol(argv[opt], &end, 16); |
241 def = defer(address, def); | 160 defer_disasm(context, address); |
242 reference(address); | |
243 if (*end == '=') { | 161 if (*end == '=') { |
244 named_labels = add_label(named_labels, end+1, address); | 162 add_label(context, end+1, address); |
163 } else { | |
164 reference(context, address); | |
245 } | 165 } |
246 } | 166 } |
247 } | 167 } |
248 FILE * f = fopen(argv[1], "rb"); | 168 FILE * f = fopen(argv[1], "rb"); |
249 fseek(f, 0, SEEK_END); | 169 fseek(f, 0, SEEK_END); |
250 filesize = ftell(f); | 170 filesize = ftell(f); |
251 fseek(f, 0, SEEK_SET); | 171 fseek(f, 0, SEEK_SET); |
252 | 172 |
253 char int_key[MAX_INT_KEY_SIZE]; | 173 char int_key[MAX_INT_KEY_SIZE]; |
254 uint8_t is_scd_iso = 0; | 174 uint8_t is_scd_iso = 0; |
255 uint8_t has_manual_defs = !!def; | 175 uint8_t has_manual_defs = !!context->deferred; |
256 if (vos) | 176 if (vos) |
257 { | 177 { |
258 vos_program_module header; | 178 vos_program_module header; |
259 vos_read_header(f, &header); | 179 vos_read_header(f, &header); |
260 vos_read_alloc_module_map(f, &header); | 180 vos_read_alloc_module_map(f, &header); |
261 address_off = header.user_boundary; | 181 address_off = header.user_boundary; |
262 address_end = address_off + filesize - 0x1000; | 182 address_end = address_off + filesize - 0x1000; |
263 def = defer(header.main_entry_link.code_address, def); | 183 defer_disasm(context, header.main_entry_link.code_address); |
264 named_labels = add_label(named_labels, "main_entry_link", header.main_entry_link.code_address); | 184 add_label(context, "main_entry_link", header.main_entry_link.code_address); |
265 for (int i = 0; i < header.n_modules; i++) | 185 for (int i = 0; i < header.n_modules; i++) |
266 { | 186 { |
267 if (!reset || header.module_map_entries[i].code_address != header.user_boundary) | 187 if (!reset || header.module_map_entries[i].code_address != header.user_boundary) |
268 { | 188 { |
269 def = defer(header.module_map_entries[i].code_address, def); | 189 defer_disasm(context, header.module_map_entries[i].code_address); |
270 } | 190 } |
271 named_labels = add_label(named_labels, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address); | 191 add_label(context, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address); |
272 } | 192 } |
273 fseek(f, 0x1000, SEEK_SET); | 193 fseek(f, 0x1000, SEEK_SET); |
274 filebuf = malloc(filesize - 0x1000); | 194 filebuf = malloc(filesize - 0x1000); |
275 if (fread(filebuf, 2, (filesize - 0x1000)/2, f) != (filesize - 0x1000)/2) | 195 if (fread(filebuf, 2, (filesize - 0x1000)/2, f) != (filesize - 0x1000)/2) |
276 { | 196 { |
281 { | 201 { |
282 *cur = (*cur >> 8) | (*cur << 8); | 202 *cur = (*cur >> 8) | (*cur << 8); |
283 } | 203 } |
284 if (reset) | 204 if (reset) |
285 { | 205 { |
286 def = defer(filebuf[2] << 16 | filebuf[3], def); | 206 defer_disasm(context, filebuf[2] << 16 | filebuf[3]); |
287 named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]); | 207 add_label(context, "reset", filebuf[2] << 16 | filebuf[3]); |
288 } | 208 } |
289 } else if (filesize > 0x1000) { | 209 } else if (filesize > 0x1000) { |
290 long boot_size = filesize > (32*1024) ? 32*1024 : filesize; | 210 long boot_size = filesize > (32*1024) ? 32*1024 : filesize; |
291 filebuf = malloc(boot_size); | 211 filebuf = malloc(boot_size); |
292 if (fread(filebuf, 1, boot_size, f) != boot_size) { | 212 if (fread(filebuf, 1, boot_size, f) != boot_size) { |
320 main_end = boot_size; | 240 main_end = boot_size; |
321 } | 241 } |
322 address_off = 0xFF0000; | 242 address_off = 0xFF0000; |
323 address_end = address_off + main_end-main_start; | 243 address_end = address_off + main_end-main_start; |
324 filebuf += main_start / 2; | 244 filebuf += main_start / 2; |
325 named_labels = add_label(named_labels, "start", 0xFF0000); | 245 add_label(context, "start", 0xFF0000); |
326 if (!has_manual_defs || !only) { | 246 if (!has_manual_defs || !only) { |
327 def = defer(0xFF0000, def); | 247 defer_disasm(context, 0xFF0000); |
328 } | 248 } |
329 uint32_t user_start; | 249 uint32_t user_start; |
330 if (filebuf[0xA/2] == 0x57A) { | 250 if (filebuf[0xA/2] == 0x57A) { |
331 //US | 251 //US |
332 user_start = 0xFF0584; | 252 user_start = 0xFF0584; |
335 user_start = 0xFF056E; | 255 user_start = 0xFF056E; |
336 } else { | 256 } else { |
337 //JP | 257 //JP |
338 user_start = 0xFF0156; | 258 user_start = 0xFF0156; |
339 } | 259 } |
340 named_labels = add_label(named_labels, "user_start", user_start); | 260 add_label(context, "user_start", user_start); |
341 do_cd_labels = 1; | 261 do_cd_labels = 1; |
342 } else { | 262 } else { |
343 uint32_t sub_start =filebuf[0x40/2] << 16 | filebuf[0x42/2]; | 263 uint32_t sub_start =filebuf[0x40/2] << 16 | filebuf[0x42/2]; |
344 uint32_t sub_end = sub_start + (filebuf[0x44/2] << 16 | filebuf[0x46/2]); | 264 uint32_t sub_end = sub_start + (filebuf[0x44/2] << 16 | filebuf[0x46/2]); |
345 if (sub_start > (boot_size - 0x20)) { | 265 if (sub_start > (boot_size - 0x20)) { |
368 } else { | 288 } else { |
369 name = namebuf; | 289 name = namebuf; |
370 sprintf(namebuf, "usercall%u", index); | 290 sprintf(namebuf, "usercall%u", index); |
371 } | 291 } |
372 uint32_t address = 0x6000 + offset - sub_start; | 292 uint32_t address = 0x6000 + offset - sub_start; |
373 named_labels = add_label(named_labels, name, address); | 293 add_label(context, name, address); |
374 if (!has_manual_defs || !only) { | 294 if (!has_manual_defs || !only) { |
375 def = defer(address, def); | 295 defer_disasm(context, address); |
376 } | 296 } |
377 } | 297 } |
378 | 298 |
379 do_cd_labels = 1; | 299 do_cd_labels = 1; |
380 filebuf += sub_start / 2; | 300 filebuf += sub_start / 2; |
406 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) | 326 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) |
407 { | 327 { |
408 *cur = (*cur >> 8) | (*cur << 8); | 328 *cur = (*cur >> 8) | (*cur << 8); |
409 } | 329 } |
410 if (!address_off) { | 330 if (!address_off) { |
411 uint32_t start = filebuf[2] << 16 | filebuf[3]; | 331 process_m68k_vectors(context, filebuf, context->deferred && only); |
412 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; | |
413 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; | |
414 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; | |
415 named_labels = add_label(named_labels, "start", start); | |
416 named_labels = add_label(named_labels, "int_2", int_2); | |
417 named_labels = add_label(named_labels, "int_4", int_4); | |
418 named_labels = add_label(named_labels, "int_6", int_6); | |
419 if (!def || !only) { | |
420 def = defer(start, def); | |
421 def = defer(int_2, def); | |
422 def = defer(int_4, def); | |
423 def = defer(int_6, def); | |
424 } | |
425 named_labels = weak_label(named_labels, "illegal_inst", filebuf[0x10/2] << 16 | filebuf[0x12/2]); | |
426 named_labels = weak_label(named_labels, "div_zero", filebuf[0x14/2] << 16 | filebuf[0x16/2]); | |
427 named_labels = weak_label(named_labels, "chk_exception", filebuf[0x18/2] << 16 | filebuf[0x1A/2]); | |
428 named_labels = weak_label(named_labels, "trapv", filebuf[0x1C/2] << 16 | filebuf[0x1E/2]); | |
429 named_labels = weak_label(named_labels, "line_a_trap", filebuf[0x28/2] << 16 | filebuf[0x2A/2]); | |
430 named_labels = weak_label(named_labels, "line_f_trap", filebuf[0x2C/2] << 16 | filebuf[0x2E/2]); | |
431 } | 332 } |
432 } | 333 } |
433 if (do_cd_labels) { | 334 if (do_cd_labels) { |
434 if (main_cpu) { | 335 if (main_cpu) { |
435 named_labels = weak_label(named_labels, "_bios_reset", 0x280); | 336 add_segacd_maincpu_labels(context); |
436 named_labels = weak_label(named_labels, "_bios_entry", 0x284); | |
437 named_labels = weak_label(named_labels, "_bios_init", 0x288); | |
438 named_labels = weak_label(named_labels, "_bios_init_sp", 0x28C); | |
439 named_labels = weak_label(named_labels, "_bios_vint", 0x290); | |
440 named_labels = weak_label(named_labels, "_bios_set_hint", 0x294); | |
441 named_labels = weak_label(named_labels, "_bios_poll_io", 0x298); | |
442 named_labels = weak_label(named_labels, "_bios_detect_io", 0x29C); | |
443 named_labels = weak_label(named_labels, "_bios_clear_vram", 0x2A0); | |
444 named_labels = weak_label(named_labels, "_bios_clear_nmtbl", 0x2A4); | |
445 named_labels = weak_label(named_labels, "_bios_clear_vsram", 0x2A8); | |
446 named_labels = weak_label(named_labels, "_bios_init_vdp", 0x2AC); | |
447 named_labels = weak_label(named_labels, "_bios_vdp_loadregs", 0x2B0); | |
448 named_labels = weak_label(named_labels, "_bios_vdp_fill", 0x2B4); | |
449 named_labels = weak_label(named_labels, "_bios_clear_vram_range", 0x2B8); | |
450 named_labels = weak_label(named_labels, "_bios_clear_vram_range_dma", 0x2BC); | |
451 named_labels = weak_label(named_labels, "_bios_vram_dma_fill", 0x2C0); | |
452 named_labels = weak_label(named_labels, "_bios_update_nmtbl", 0x2C4); | |
453 named_labels = weak_label(named_labels, "_bios_update_nmtbl_template", 0x2C8); | |
454 named_labels = weak_label(named_labels, "_bios_fill_nmtbl", 0x2CC); | |
455 named_labels = weak_label(named_labels, "_bios_vdp_dma", 0x2D0); | |
456 named_labels = weak_label(named_labels, "_bios_vdp_dma_wordram", 0x2D4); | |
457 named_labels = weak_label(named_labels, "_bios_vdp_display_enable", 0x2D8); | |
458 named_labels = weak_label(named_labels, "_bios_vdp_display_disable", 0x2DC); | |
459 named_labels = weak_label(named_labels, "_bios_pal_buffer", 0x2E0); | |
460 named_labels = weak_label(named_labels, "_bios_pal_buffer_update", 0x2E4); | |
461 named_labels = weak_label(named_labels, "_bios_pal_dma", 0x2E8); | |
462 named_labels = weak_label(named_labels, "_bios_gfx_decomp", 0x2EC); | |
463 named_labels = weak_label(named_labels, "_bios_gfx_decomp_ram", 0x2F0); | |
464 named_labels = weak_label(named_labels, "_bios_update_sprites", 0x2F4); | |
465 named_labels = weak_label(named_labels, "_bios_clear_ram", 0x2F8); | |
466 named_labels = weak_label(named_labels, "_bios_display_sprite", 0x300); | |
467 named_labels = weak_label(named_labels, "_bios_wait_vint", 0x304); | |
468 named_labels = weak_label(named_labels, "_bios_wait_vint_flags", 0x308); | |
469 named_labels = weak_label(named_labels, "_bios_dma_sat", 0x30C); | |
470 named_labels = weak_label(named_labels, "_bios_set_hint_direct", 0x314); | |
471 named_labels = weak_label(named_labels, "_bios_disable_hint", 0x318); | |
472 named_labels = weak_label(named_labels, "_bios_print", 0x31C); | |
473 named_labels = weak_label(named_labels, "_bios_load_user_font", 0x320); | |
474 named_labels = weak_label(named_labels, "_bios_load_bios_font", 0x324); | |
475 named_labels = weak_label(named_labels, "_bios_load_bios_font_default", 0x328); | |
476 //TODO: more functions in the middle here | |
477 named_labels = weak_label(named_labels, "_bios_prng_mod", 0x338); | |
478 named_labels = weak_label(named_labels, "_bios_prng", 0x33C); | |
479 named_labels = weak_label(named_labels, "_bios_clear_comm", 0x340); | |
480 named_labels = weak_label(named_labels, "_bios_comm_update", 0x344); | |
481 //TODO: more functions in the middle here | |
482 named_labels = weak_label(named_labels, "_bios_sega_logo", 0x364); | |
483 named_labels = weak_label(named_labels, "_bios_set_vint", 0x368); | |
484 //TODO: more functions at the end here | |
485 | |
486 named_labels = weak_label(named_labels, "WORD_RAM", 0x200000); | |
487 named_labels = weak_label(named_labels, "CD_RESET_IFL2", 0xA12000); | |
488 named_labels = weak_label(named_labels, "CD_RESET_IFL2_BYTE", 0xA12001); | |
489 named_labels = weak_label(named_labels, "CD_WRITE_PROTECT", 0xA12002); | |
490 named_labels = weak_label(named_labels, "CD_MEM_MODE", 0xA12003); | |
491 named_labels = weak_label(named_labels, "CDC_CTRL", 0xA12004); | |
492 named_labels = weak_label(named_labels, "HINT_VECTOR", 0xA12006); | |
493 named_labels = weak_label(named_labels, "CDC_HOST_DATA", 0xA12008); | |
494 named_labels = weak_label(named_labels, "STOP_WATCH", 0xA1200C); | |
495 named_labels = weak_label(named_labels, "COMM_MAIN_FLAG", 0xA1200E); | |
496 named_labels = weak_label(named_labels, "COMM_SUB_FLAG", 0xA1200F); | |
497 named_labels = weak_label(named_labels, "COMM_CMD0", 0xA12010); | |
498 named_labels = weak_label(named_labels, "COMM_CMD1", 0xA12012); | |
499 named_labels = weak_label(named_labels, "COMM_CMD2", 0xA12014); | |
500 named_labels = weak_label(named_labels, "COMM_CMD3", 0xA12016); | |
501 named_labels = weak_label(named_labels, "COMM_CMD4", 0xA12018); | |
502 named_labels = weak_label(named_labels, "COMM_CMD5", 0xA1201A); | |
503 named_labels = weak_label(named_labels, "COMM_CMD6", 0xA1201C); | |
504 named_labels = weak_label(named_labels, "COMM_CMD7", 0xA1201E); | |
505 named_labels = weak_label(named_labels, "COMM_STATUS0", 0xA12020); | |
506 named_labels = weak_label(named_labels, "COMM_STATUS1", 0xA12022); | |
507 named_labels = weak_label(named_labels, "COMM_STATUS2", 0xA12024); | |
508 named_labels = weak_label(named_labels, "COMM_STATUS3", 0xA12026); | |
509 named_labels = weak_label(named_labels, "COMM_STATUS4", 0xA12028); | |
510 named_labels = weak_label(named_labels, "COMM_STATUS5", 0xA1202A); | |
511 named_labels = weak_label(named_labels, "COMM_STATUS6", 0xA1202C); | |
512 named_labels = weak_label(named_labels, "COMM_STATUS7", 0xA1202E); | |
513 } else { | 337 } else { |
514 named_labels = weak_label(named_labels, "bios_common_work", 0x5E80); | 338 add_segacd_subcpu_labels(context); |
515 named_labels = weak_label(named_labels, "_setjmptbl", 0x5F0A); | |
516 named_labels = weak_label(named_labels, "_waitvsync", 0x5F10); | |
517 named_labels = weak_label(named_labels, "_buram", 0x5F16); | |
518 named_labels = weak_label(named_labels, "_cdboot", 0x5F1C); | |
519 named_labels = weak_label(named_labels, "_cdbios", 0x5F22); | |
520 named_labels = weak_label(named_labels, "_usercall0", 0x5F28); | |
521 named_labels = weak_label(named_labels, "_usercall1", 0x5F2E); | |
522 named_labels = weak_label(named_labels, "_usercall2", 0x5F34); | |
523 named_labels = weak_label(named_labels, "_usercall2Address", 0x5F36); | |
524 named_labels = weak_label(named_labels, "_usercall3", 0x5F3A); | |
525 named_labels = weak_label(named_labels, "_adrerr", 0x5F40); | |
526 named_labels = weak_label(named_labels, "_adrerrAddress", 0x5F42); | |
527 named_labels = weak_label(named_labels, "_coderr", 0x5F46); | |
528 named_labels = weak_label(named_labels, "_coderrAddress", 0x5F48); | |
529 named_labels = weak_label(named_labels, "_diverr", 0x5F4C); | |
530 named_labels = weak_label(named_labels, "_diverrAddress", 0x5F4E); | |
531 named_labels = weak_label(named_labels, "_chkerr", 0x5F52); | |
532 named_labels = weak_label(named_labels, "_chkerrAddress", 0x5F54); | |
533 named_labels = weak_label(named_labels, "_trperr", 0x5F58); | |
534 named_labels = weak_label(named_labels, "_trperrAddress", 0x5F5A); | |
535 named_labels = weak_label(named_labels, "_spverr", 0x5F5E); | |
536 named_labels = weak_label(named_labels, "_spverrAddress", 0x5F60); | |
537 named_labels = weak_label(named_labels, "_trace", 0x5F64); | |
538 named_labels = weak_label(named_labels, "_traceAddress", 0x5F66); | |
539 named_labels = weak_label(named_labels, "_nocod0", 0x5F6A); | |
540 named_labels = weak_label(named_labels, "_nocod0Address", 0x5F6C); | |
541 named_labels = weak_label(named_labels, "_nocod0", 0x5F70); | |
542 named_labels = weak_label(named_labels, "_nocod0Address", 0x5F72); | |
543 named_labels = weak_label(named_labels, "_slevel1", 0x5F76); | |
544 named_labels = weak_label(named_labels, "_slevel1Address", 0x5F78); | |
545 named_labels = weak_label(named_labels, "_slevel2", 0x5F7C); | |
546 named_labels = weak_label(named_labels, "_slevel2Address", 0x5F7E); | |
547 named_labels = weak_label(named_labels, "_slevel3", 0x5F82); | |
548 named_labels = weak_label(named_labels, "_slevel3Address", 0x5F84); | |
549 named_labels = weak_label(named_labels, "WORD_RAM_2M", 0x80000); | |
550 named_labels = weak_label(named_labels, "WORD_RAM_1M", 0xC0000); | |
551 named_labels = weak_label(named_labels, "LED_CONTROL", 0xFFFF8000); | |
552 named_labels = weak_label(named_labels, "VERSION_RESET", 0xFFFF8001); | |
553 named_labels = weak_label(named_labels, "MEM_MODE_WORD", 0xFFFF8002); | |
554 named_labels = weak_label(named_labels, "MEM_MODE_BYTE", 0xFFFF8003); | |
555 named_labels = weak_label(named_labels, "CDC_CTRL", 0xFFFF8004); | |
556 named_labels = weak_label(named_labels, "CDC_AR", 0xFFFF8005); | |
557 named_labels = weak_label(named_labels, "CDC_REG_DATA_WORD", 0xFFFF8006); | |
558 named_labels = weak_label(named_labels, "CDC_REG_DATA", 0xFFFF8007); | |
559 named_labels = weak_label(named_labels, "CDC_HOST_DATA", 0xFFFF8008); | |
560 named_labels = weak_label(named_labels, "CDC_DMA_ADDR", 0xFFFF800A); | |
561 named_labels = weak_label(named_labels, "STOP_WATCH", 0xFFFF800C); | |
562 named_labels = weak_label(named_labels, "COMM_MAIN_FLAG", 0xFFFF800E); | |
563 named_labels = weak_label(named_labels, "COMM_SUB_FLAG", 0xFFFF800F); | |
564 named_labels = weak_label(named_labels, "COMM_CMD0", 0xFFFF8010); | |
565 named_labels = weak_label(named_labels, "COMM_CMD1", 0xFFFF8012); | |
566 named_labels = weak_label(named_labels, "COMM_CMD2", 0xFFFF8014); | |
567 named_labels = weak_label(named_labels, "COMM_CMD3", 0xFFFF8016); | |
568 named_labels = weak_label(named_labels, "COMM_CMD4", 0xFFFF8018); | |
569 named_labels = weak_label(named_labels, "COMM_CMD5", 0xFFFF801A); | |
570 named_labels = weak_label(named_labels, "COMM_CMD6", 0xFFFF801C); | |
571 named_labels = weak_label(named_labels, "COMM_CMD7", 0xFFFF801E); | |
572 named_labels = weak_label(named_labels, "COMM_STATUS0", 0xFFFF8020); | |
573 named_labels = weak_label(named_labels, "COMM_STATUS1", 0xFFFF8022); | |
574 named_labels = weak_label(named_labels, "COMM_STATUS2", 0xFFFF8024); | |
575 named_labels = weak_label(named_labels, "COMM_STATUS3", 0xFFFF8026); | |
576 named_labels = weak_label(named_labels, "COMM_STATUS4", 0xFFFF8028); | |
577 named_labels = weak_label(named_labels, "COMM_STATUS5", 0xFFFF802A); | |
578 named_labels = weak_label(named_labels, "COMM_STATUS6", 0xFFFF802C); | |
579 named_labels = weak_label(named_labels, "COMM_STATUS7", 0xFFFF802E); | |
580 named_labels = weak_label(named_labels, "TIMER_WORD", 0xFFFF8030); | |
581 named_labels = weak_label(named_labels, "TIMER", 0xFFFF8031); | |
582 named_labels = weak_label(named_labels, "INT_MASK_WORD", 0xFFFF8032); | |
583 named_labels = weak_label(named_labels, "INT_MASK", 0xFFFF8033); | |
584 named_labels = weak_label(named_labels, "CDD_FADER", 0xFFFF8034); | |
585 named_labels = weak_label(named_labels, "CDD_CTRL_WORD", 0xFFFF8036); | |
586 named_labels = weak_label(named_labels, "CDD_CTRL_BYTE", 0xFFFF8037); | |
587 } | 339 } |
588 } | 340 } |
589 uint32_t size, tmp_addr; | 341 uint32_t size, tmp_addr; |
590 uint32_t address; | 342 uint32_t address; |
591 rom_def rom = { | 343 rom_def rom = { |
592 .address_off = address_off, | 344 .address_off = address_off, |
593 .address_end = address_end, | 345 .address_end = address_end, |
594 .buffer = filebuf | 346 .buffer = filebuf |
595 }; | 347 }; |
596 uint8_t valid_address; | 348 uint8_t valid_address; |
597 while(def) { | 349 while(context->deferred) { |
598 do { | 350 do { |
599 valid_address = 0; | 351 valid_address = 0; |
600 address = def->address; | 352 address = context->deferred->address; |
601 if (!is_visited(address)) { | 353 if (!is_visited(context, address)) { |
602 address &= 0xFFFFFF; | 354 address &= context->address_mask; |
603 if (address < address_end && address >= address_off) { | 355 if (address < address_end && address >= address_off) { |
604 valid_address = 1; | 356 valid_address = 1; |
605 } | 357 address = context->deferred->address; |
606 } | 358 } |
607 tmpd = def; | 359 } |
608 def = def->next; | 360 deferred_addr *tmpd = context->deferred; |
361 context->deferred = context->deferred->next; | |
609 free(tmpd); | 362 free(tmpd); |
610 } while(def && !valid_address); | 363 } while(context->deferred && !valid_address); |
611 if (!valid_address) { | 364 if (!valid_address) { |
612 break; | 365 break; |
613 } | 366 } |
614 for(;;) { | 367 for(;;) { |
615 if ((address & 0xFFFFFF) > address_end || address < address_off) { | 368 if ((address & context->address_mask) > address_end || address < address_off) { |
616 break; | 369 break; |
617 } | 370 } |
618 visit(address); | 371 visit(context, address); |
619 address = m68k_decode(fetch, &rom, &instbuf, address); | 372 address = m68k_decode(fetch, &rom, &instbuf, address); |
620 //m68k_disasm(&instbuf, disbuf); | 373 //m68k_disasm(&instbuf, disbuf); |
621 //printf("%X: %s\n", instbuf.address, disbuf); | 374 //printf("%X: %s\n", instbuf.address, disbuf); |
622 check_reference(&instbuf, &(instbuf.src)); | 375 check_reference(context, &instbuf, &(instbuf.src)); |
623 check_reference(&instbuf, &(instbuf.dst)); | 376 check_reference(context, &instbuf, &(instbuf.dst)); |
624 if (instbuf.op == M68K_ILLEGAL || instbuf.op == M68K_RTS || instbuf.op == M68K_RTE || instbuf.op == M68K_INVALID) { | 377 if (instbuf.op == M68K_ILLEGAL || instbuf.op == M68K_RTS || instbuf.op == M68K_RTE || instbuf.op == M68K_INVALID) { |
625 break; | 378 break; |
626 } | 379 } |
627 if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) { | 380 if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) { |
381 tmp_addr = instbuf.address + 2 + instbuf.src.params.immed; | |
382 reference(context, tmp_addr); | |
628 if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) { | 383 if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) { |
629 address = instbuf.address + 2 + instbuf.src.params.immed; | 384 address = tmp_addr; |
630 reference(address); | 385 if (is_visited(context, address)) { |
631 if (is_visited(address)) { | |
632 break; | 386 break; |
633 } | 387 } |
634 } else { | 388 } else { |
635 tmp_addr = instbuf.address + 2 + instbuf.src.params.immed; | 389 defer_disasm(context, tmp_addr); |
636 reference(tmp_addr); | |
637 def = defer(tmp_addr, def); | |
638 } | 390 } |
639 } else if(instbuf.op == M68K_JMP) { | 391 } else if(instbuf.op == M68K_JMP) { |
640 if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { | 392 if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { |
641 address = instbuf.src.params.immed; | 393 address = instbuf.src.params.immed; |
642 if (is_visited(address)) { | 394 if (is_visited(context, address)) { |
643 break; | 395 break; |
644 } | 396 } |
645 } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { | 397 } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { |
646 address = instbuf.src.params.regs.displacement + instbuf.address + 2; | 398 address = instbuf.src.params.regs.displacement + instbuf.address + 2; |
647 if (is_visited(address)) { | 399 if (is_visited(context, address)) { |
648 break; | 400 break; |
649 } | 401 } |
650 } else { | 402 } else { |
651 break; | 403 break; |
652 } | 404 } |
653 } else if(instbuf.op == M68K_JSR) { | 405 } else if(instbuf.op == M68K_JSR) { |
654 if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { | 406 if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { |
655 def = defer(instbuf.src.params.immed, def); | 407 defer_disasm(context, instbuf.src.params.immed); |
656 } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { | 408 } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { |
657 def = defer(instbuf.src.params.regs.displacement + instbuf.address + 2, def); | 409 defer_disasm(context, instbuf.src.params.regs.displacement + instbuf.address + 2); |
658 } | 410 } |
659 } | 411 } |
660 } | 412 } |
661 } | 413 } |
662 if (labels) { | 414 if (labels) { |
663 for (address = 0; address < address_off; address++) { | 415 tern_foreach(context->labels, print_label_def, &rom); |
664 if (is_label(address)) { | |
665 char key[MAX_INT_KEY_SIZE]; | |
666 tern_int_key(address, key); | |
667 label_names *names = tern_find_ptr(named_labels, key); | |
668 if (names) { | |
669 for (int i = 0; i < names->num_labels; i++) | |
670 { | |
671 printf("%s equ $%X\n", names->labels[i], address); | |
672 } | |
673 } else { | |
674 printf("ADR_%X equ $%X\n", address, address); | |
675 } | |
676 } | |
677 } | |
678 for (address = address_end; address < (16*1024*1024); address++) { | |
679 if (is_label(address)) { | |
680 char key[MAX_INT_KEY_SIZE]; | |
681 tern_int_key(address, key); | |
682 label_names *names = tern_find_ptr(named_labels, key); | |
683 if (names) { | |
684 for (int i = 0; i < names->num_labels; i++) | |
685 { | |
686 printf("%s equ $%X\n", names->labels[i], names->full_address); | |
687 } | |
688 } else { | |
689 printf("ADR_%X equ $%X\n", address, address); | |
690 } | |
691 } | |
692 } | |
693 puts(""); | 416 puts(""); |
694 } | 417 } |
695 for (address = address_off; address < address_end; address+=2) { | 418 for (address = address_off; address < address_end; address+=2) { |
696 if (is_visited(address)) { | 419 if (is_visited(context, address)) { |
697 m68k_decode(fetch, &rom, &instbuf, address); | 420 m68k_decode(fetch, &rom, &instbuf, address); |
698 if (labels) { | 421 if (labels) { |
699 m68k_disasm_labels(&instbuf, disbuf, label_fun, named_labels); | 422 m68k_disasm_labels(&instbuf, disbuf, label_fun, context); |
700 char keybuf[MAX_INT_KEY_SIZE]; | 423 label_def *label = find_label(context, address); |
701 label_names * names = tern_find_ptr(named_labels, tern_int_key(address, keybuf)); | 424 if (label) { |
702 if (names) | 425 if (label->num_labels) { |
703 { | 426 for (int i = 0; i < label->num_labels; i++) |
704 for (int i = 0; i < names->num_labels; i++) | 427 { |
705 { | 428 printf("%s:\n", label->labels[i]); |
706 printf("%s:\n", names->labels[i]); | 429 } |
707 } | 430 } else { |
708 } else if (is_label(instbuf.address)) { | 431 printf("ADR_%X:\n", label->full_address); |
709 printf("ADR_%X:\n", instbuf.address); | 432 } |
710 } | 433 } |
711 if (addr) { | 434 if (addr) { |
712 printf("\t%s\t;%X\n", disbuf, instbuf.address); | 435 printf("\t%s\t;%X\n", disbuf, instbuf.address); |
713 } else { | 436 } else { |
714 printf("\t%s\n", disbuf); | 437 printf("\t%s\n", disbuf); |