# HG changeset patch # User Michael Pavone # Date 1661645277 25200 # Node ID 4c265d2f6c880d35e10387f9ca18e0501c8e53e3 # Parent 90297f1fb3fec3a6fe6497ae43fcd2d120ded705 Minor refactor of 68K disassembler diff -r 90297f1fb3fe -r 4c265d2f6c88 Makefile --- a/Makefile Tue Aug 23 20:21:26 2022 -0700 +++ b/Makefile Sat Aug 27 17:07:57 2022 -0700 @@ -287,7 +287,7 @@ termhelper : termhelper.o $(CC) -o $@ $^ $(LDFLAGS) -dis$(EXE) : dis.o 68kinst.o tern.o vos_program_module.o +dis$(EXE) : dis.o disasm.o backend.o 68kinst.o tern.o vos_program_module.o util.o $(CC) -o $@ $^ $(OPT) jagdis : jagdis.o jagcpu.o tern.o diff -r 90297f1fb3fe -r 4c265d2f6c88 dis.c --- a/dis.c Tue Aug 23 20:21:26 2022 -0700 +++ b/dis.c Sat Aug 27 17:07:57 2022 -0700 @@ -12,138 +12,35 @@ #include "vos_program_module.h" #include "tern.h" #include "util.h" - -uint8_t visited[(16*1024*1024)/16]; -uint16_t label[(16*1024*1024)/8]; - -void fatal_error(char *format, ...) -{ - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - exit(1); -} - - -void visit(uint32_t address) -{ - address &= 0xFFFFFF; - visited[address/16] |= 1 << ((address / 2) % 8); -} - -void reference(uint32_t address) -{ - address &= 0xFFFFFF; - //printf("referenced: %X\n", address); - label[address/16] |= 1 << (address % 16); -} - -uint8_t is_visited(uint32_t address) -{ - address &= 0xFFFFFF; - return visited[address/16] & (1 << ((address / 2) % 8)); -} - -uint16_t is_label(uint32_t address) -{ - address &= 0xFFFFFF; - return label[address/16] & (1 << (address % 16)); -} - -typedef struct { - uint32_t num_labels; - uint32_t storage; - uint32_t full_address; - char *labels[]; -} label_names; +#include "disasm.h" -tern_node * weak_label(tern_node * head, const char *name, uint32_t address) -{ - char key[MAX_INT_KEY_SIZE]; - tern_int_key(address & 0xFFFFFF, key); - label_names * names = tern_find_ptr(head, key); - if (names) - { - if (names->num_labels == names->storage) - { - names->storage = names->storage + (names->storage >> 1); - names = realloc(names, sizeof(label_names) + names->storage * sizeof(char *)); - } - } else { - names = malloc(sizeof(label_names) + 4 * sizeof(char *)); - names->num_labels = 0; - names->storage = 4; - head = tern_insert_ptr(head, key, names); - } - names->labels[names->num_labels++] = strdup(name); - names->full_address = address; - return head; -} -tern_node *add_label(tern_node * head, const char *name, uint32_t address) -{ - reference(address); - return weak_label(head, name, address); -} +int headless; +void render_errorbox(char *title, char *message) {} +void render_warnbox(char *title, char *message) {} +void render_infobox(char *title, char *message) {} -typedef struct deferred { - uint32_t address; - struct deferred *next; -} deferred; - -deferred * defer(uint32_t address, deferred * next) -{ - if (is_visited(address) || address & 1) { - return next; - } - //printf("deferring %X\n", address); - deferred * d = malloc(sizeof(deferred)); - d->address = address; - d->next = next; - return d; -} - -void check_reference(m68kinst * inst, m68k_op_info * op) +void check_reference(disasm_context *context, m68kinst * inst, m68k_op_info * op) { switch(op->addr_mode) { case MODE_PC_DISPLACE: - reference(inst->address + 2 + op->params.regs.displacement); + reference(context, inst->address + 2 + op->params.regs.displacement); break; case MODE_ABSOLUTE: case MODE_ABSOLUTE_SHORT: - reference(op->params.immed); + reference(context, op->params.immed); break; } } int label_fun(char *dst, uint32_t address, void * data) { - tern_node * labels = data; - char key[MAX_INT_KEY_SIZE]; - label_names * names = tern_find_ptr(labels, tern_int_key(address & 0xFFFFFF, key)); - if (names) - { - return sprintf(dst, "%s", names->labels[0]); - } else { - return m68k_default_label_fun(dst, address, NULL); + disasm_context *context = data; + label_def *def = find_label(context, address); + if (def && def->num_labels) { + return sprintf(dst, "%s", def->labels[0]); } -} - -char * strip_ws(char * text) -{ - while (*text && (!isprint(*text) || isblank(*text))) - { - text++; - } - char * ret = text; - text = ret + strlen(ret) - 1; - while (text > ret && (!isprint(*text) || isblank(*text))) - { - *text = 0; - text--; - } - return ret; + return m68k_default_label_fun(dst, address, NULL); } typedef struct { @@ -161,6 +58,27 @@ return 0; } +void print_label_def(char *key, tern_val val, uint8_t valtype, void *data) +{ + rom_def *rom = data; + label_def *label = val.ptrval; + uint32_t address = label->full_address & 0xFFFFFFF; + if (address >= rom->address_off && address < rom->address_end) { + return; + } + if (!label->referenced) { + return; + } + if (label->num_labels) { + for (int i = 0; i < label->num_labels; i++) + { + printf("%s equ $%X\n", label->labels[i], label->full_address); + } + } else { + printf("ADR_%X equ $%X\n", label->full_address, label->full_address); + } +} + int main(int argc, char ** argv) { long filesize; @@ -168,10 +86,10 @@ char disbuf[1024]; m68kinst instbuf; unsigned short * cur; - deferred *def = NULL, *tmpd; uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0; - tern_node * named_labels = NULL; + disasm_context *context = create_68000_disasm(); + uint32_t address_off = 0, address_end; uint8_t do_cd_labels = 0, main_cpu = 0; @@ -225,10 +143,11 @@ char *end; uint32_t address = strtol(disbuf, &end, 16); if (address) { - def = defer(address, def); - reference(address); + defer_disasm(context, address); if (*end == '=') { - named_labels = add_label(named_labels, strip_ws(end+1), address); + add_label(context, strip_ws(end+1), address); + } else { + reference(context, address); } } } @@ -238,10 +157,11 @@ } else { char *end; uint32_t address = strtol(argv[opt], &end, 16); - def = defer(address, def); - reference(address); + defer_disasm(context, address); if (*end == '=') { - named_labels = add_label(named_labels, end+1, address); + add_label(context, end+1, address); + } else { + reference(context, address); } } } @@ -252,7 +172,7 @@ char int_key[MAX_INT_KEY_SIZE]; uint8_t is_scd_iso = 0; - uint8_t has_manual_defs = !!def; + uint8_t has_manual_defs = !!context->deferred; if (vos) { vos_program_module header; @@ -260,15 +180,15 @@ vos_read_alloc_module_map(f, &header); address_off = header.user_boundary; address_end = address_off + filesize - 0x1000; - def = defer(header.main_entry_link.code_address, def); - named_labels = add_label(named_labels, "main_entry_link", header.main_entry_link.code_address); + defer_disasm(context, header.main_entry_link.code_address); + add_label(context, "main_entry_link", header.main_entry_link.code_address); for (int i = 0; i < header.n_modules; i++) { if (!reset || header.module_map_entries[i].code_address != header.user_boundary) { - def = defer(header.module_map_entries[i].code_address, def); + defer_disasm(context, header.module_map_entries[i].code_address); } - named_labels = add_label(named_labels, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address); + add_label(context, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address); } fseek(f, 0x1000, SEEK_SET); filebuf = malloc(filesize - 0x1000); @@ -283,8 +203,8 @@ } if (reset) { - def = defer(filebuf[2] << 16 | filebuf[3], def); - named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]); + defer_disasm(context, filebuf[2] << 16 | filebuf[3]); + add_label(context, "reset", filebuf[2] << 16 | filebuf[3]); } } else if (filesize > 0x1000) { long boot_size = filesize > (32*1024) ? 32*1024 : filesize; @@ -322,9 +242,9 @@ address_off = 0xFF0000; address_end = address_off + main_end-main_start; filebuf += main_start / 2; - named_labels = add_label(named_labels, "start", 0xFF0000); + add_label(context, "start", 0xFF0000); if (!has_manual_defs || !only) { - def = defer(0xFF0000, def); + defer_disasm(context, 0xFF0000); } uint32_t user_start; if (filebuf[0xA/2] == 0x57A) { @@ -337,7 +257,7 @@ //JP user_start = 0xFF0156; } - named_labels = add_label(named_labels, "user_start", user_start); + add_label(context, "user_start", user_start); do_cd_labels = 1; } else { uint32_t sub_start =filebuf[0x40/2] << 16 | filebuf[0x42/2]; @@ -370,9 +290,9 @@ sprintf(namebuf, "usercall%u", index); } uint32_t address = 0x6000 + offset - sub_start; - named_labels = add_label(named_labels, name, address); + add_label(context, name, address); if (!has_manual_defs || !only) { - def = defer(address, def); + defer_disasm(context, address); } } @@ -408,182 +328,14 @@ *cur = (*cur >> 8) | (*cur << 8); } if (!address_off) { - uint32_t start = filebuf[2] << 16 | filebuf[3]; - uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; - uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; - uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; - named_labels = add_label(named_labels, "start", start); - named_labels = add_label(named_labels, "int_2", int_2); - named_labels = add_label(named_labels, "int_4", int_4); - named_labels = add_label(named_labels, "int_6", int_6); - if (!def || !only) { - def = defer(start, def); - def = defer(int_2, def); - def = defer(int_4, def); - def = defer(int_6, def); - } - named_labels = weak_label(named_labels, "illegal_inst", filebuf[0x10/2] << 16 | filebuf[0x12/2]); - named_labels = weak_label(named_labels, "div_zero", filebuf[0x14/2] << 16 | filebuf[0x16/2]); - named_labels = weak_label(named_labels, "chk_exception", filebuf[0x18/2] << 16 | filebuf[0x1A/2]); - named_labels = weak_label(named_labels, "trapv", filebuf[0x1C/2] << 16 | filebuf[0x1E/2]); - named_labels = weak_label(named_labels, "line_a_trap", filebuf[0x28/2] << 16 | filebuf[0x2A/2]); - named_labels = weak_label(named_labels, "line_f_trap", filebuf[0x2C/2] << 16 | filebuf[0x2E/2]); + process_m68k_vectors(context, filebuf, context->deferred && only); } } if (do_cd_labels) { if (main_cpu) { - named_labels = weak_label(named_labels, "_bios_reset", 0x280); - named_labels = weak_label(named_labels, "_bios_entry", 0x284); - named_labels = weak_label(named_labels, "_bios_init", 0x288); - named_labels = weak_label(named_labels, "_bios_init_sp", 0x28C); - named_labels = weak_label(named_labels, "_bios_vint", 0x290); - named_labels = weak_label(named_labels, "_bios_set_hint", 0x294); - named_labels = weak_label(named_labels, "_bios_poll_io", 0x298); - named_labels = weak_label(named_labels, "_bios_detect_io", 0x29C); - named_labels = weak_label(named_labels, "_bios_clear_vram", 0x2A0); - named_labels = weak_label(named_labels, "_bios_clear_nmtbl", 0x2A4); - named_labels = weak_label(named_labels, "_bios_clear_vsram", 0x2A8); - named_labels = weak_label(named_labels, "_bios_init_vdp", 0x2AC); - named_labels = weak_label(named_labels, "_bios_vdp_loadregs", 0x2B0); - named_labels = weak_label(named_labels, "_bios_vdp_fill", 0x2B4); - named_labels = weak_label(named_labels, "_bios_clear_vram_range", 0x2B8); - named_labels = weak_label(named_labels, "_bios_clear_vram_range_dma", 0x2BC); - named_labels = weak_label(named_labels, "_bios_vram_dma_fill", 0x2C0); - named_labels = weak_label(named_labels, "_bios_update_nmtbl", 0x2C4); - named_labels = weak_label(named_labels, "_bios_update_nmtbl_template", 0x2C8); - named_labels = weak_label(named_labels, "_bios_fill_nmtbl", 0x2CC); - named_labels = weak_label(named_labels, "_bios_vdp_dma", 0x2D0); - named_labels = weak_label(named_labels, "_bios_vdp_dma_wordram", 0x2D4); - named_labels = weak_label(named_labels, "_bios_vdp_display_enable", 0x2D8); - named_labels = weak_label(named_labels, "_bios_vdp_display_disable", 0x2DC); - named_labels = weak_label(named_labels, "_bios_pal_buffer", 0x2E0); - named_labels = weak_label(named_labels, "_bios_pal_buffer_update", 0x2E4); - named_labels = weak_label(named_labels, "_bios_pal_dma", 0x2E8); - named_labels = weak_label(named_labels, "_bios_gfx_decomp", 0x2EC); - named_labels = weak_label(named_labels, "_bios_gfx_decomp_ram", 0x2F0); - named_labels = weak_label(named_labels, "_bios_update_sprites", 0x2F4); - named_labels = weak_label(named_labels, "_bios_clear_ram", 0x2F8); - named_labels = weak_label(named_labels, "_bios_display_sprite", 0x300); - named_labels = weak_label(named_labels, "_bios_wait_vint", 0x304); - named_labels = weak_label(named_labels, "_bios_wait_vint_flags", 0x308); - named_labels = weak_label(named_labels, "_bios_dma_sat", 0x30C); - named_labels = weak_label(named_labels, "_bios_set_hint_direct", 0x314); - named_labels = weak_label(named_labels, "_bios_disable_hint", 0x318); - named_labels = weak_label(named_labels, "_bios_print", 0x31C); - named_labels = weak_label(named_labels, "_bios_load_user_font", 0x320); - named_labels = weak_label(named_labels, "_bios_load_bios_font", 0x324); - named_labels = weak_label(named_labels, "_bios_load_bios_font_default", 0x328); - //TODO: more functions in the middle here - named_labels = weak_label(named_labels, "_bios_prng_mod", 0x338); - named_labels = weak_label(named_labels, "_bios_prng", 0x33C); - named_labels = weak_label(named_labels, "_bios_clear_comm", 0x340); - named_labels = weak_label(named_labels, "_bios_comm_update", 0x344); - //TODO: more functions in the middle here - named_labels = weak_label(named_labels, "_bios_sega_logo", 0x364); - named_labels = weak_label(named_labels, "_bios_set_vint", 0x368); - //TODO: more functions at the end here - - named_labels = weak_label(named_labels, "WORD_RAM", 0x200000); - named_labels = weak_label(named_labels, "CD_RESET_IFL2", 0xA12000); - named_labels = weak_label(named_labels, "CD_RESET_IFL2_BYTE", 0xA12001); - named_labels = weak_label(named_labels, "CD_WRITE_PROTECT", 0xA12002); - named_labels = weak_label(named_labels, "CD_MEM_MODE", 0xA12003); - named_labels = weak_label(named_labels, "CDC_CTRL", 0xA12004); - named_labels = weak_label(named_labels, "HINT_VECTOR", 0xA12006); - named_labels = weak_label(named_labels, "CDC_HOST_DATA", 0xA12008); - named_labels = weak_label(named_labels, "STOP_WATCH", 0xA1200C); - named_labels = weak_label(named_labels, "COMM_MAIN_FLAG", 0xA1200E); - named_labels = weak_label(named_labels, "COMM_SUB_FLAG", 0xA1200F); - named_labels = weak_label(named_labels, "COMM_CMD0", 0xA12010); - named_labels = weak_label(named_labels, "COMM_CMD1", 0xA12012); - named_labels = weak_label(named_labels, "COMM_CMD2", 0xA12014); - named_labels = weak_label(named_labels, "COMM_CMD3", 0xA12016); - named_labels = weak_label(named_labels, "COMM_CMD4", 0xA12018); - named_labels = weak_label(named_labels, "COMM_CMD5", 0xA1201A); - named_labels = weak_label(named_labels, "COMM_CMD6", 0xA1201C); - named_labels = weak_label(named_labels, "COMM_CMD7", 0xA1201E); - named_labels = weak_label(named_labels, "COMM_STATUS0", 0xA12020); - named_labels = weak_label(named_labels, "COMM_STATUS1", 0xA12022); - named_labels = weak_label(named_labels, "COMM_STATUS2", 0xA12024); - named_labels = weak_label(named_labels, "COMM_STATUS3", 0xA12026); - named_labels = weak_label(named_labels, "COMM_STATUS4", 0xA12028); - named_labels = weak_label(named_labels, "COMM_STATUS5", 0xA1202A); - named_labels = weak_label(named_labels, "COMM_STATUS6", 0xA1202C); - named_labels = weak_label(named_labels, "COMM_STATUS7", 0xA1202E); + add_segacd_maincpu_labels(context); } else { - named_labels = weak_label(named_labels, "bios_common_work", 0x5E80); - named_labels = weak_label(named_labels, "_setjmptbl", 0x5F0A); - named_labels = weak_label(named_labels, "_waitvsync", 0x5F10); - named_labels = weak_label(named_labels, "_buram", 0x5F16); - named_labels = weak_label(named_labels, "_cdboot", 0x5F1C); - named_labels = weak_label(named_labels, "_cdbios", 0x5F22); - named_labels = weak_label(named_labels, "_usercall0", 0x5F28); - named_labels = weak_label(named_labels, "_usercall1", 0x5F2E); - named_labels = weak_label(named_labels, "_usercall2", 0x5F34); - named_labels = weak_label(named_labels, "_usercall2Address", 0x5F36); - named_labels = weak_label(named_labels, "_usercall3", 0x5F3A); - named_labels = weak_label(named_labels, "_adrerr", 0x5F40); - named_labels = weak_label(named_labels, "_adrerrAddress", 0x5F42); - named_labels = weak_label(named_labels, "_coderr", 0x5F46); - named_labels = weak_label(named_labels, "_coderrAddress", 0x5F48); - named_labels = weak_label(named_labels, "_diverr", 0x5F4C); - named_labels = weak_label(named_labels, "_diverrAddress", 0x5F4E); - named_labels = weak_label(named_labels, "_chkerr", 0x5F52); - named_labels = weak_label(named_labels, "_chkerrAddress", 0x5F54); - named_labels = weak_label(named_labels, "_trperr", 0x5F58); - named_labels = weak_label(named_labels, "_trperrAddress", 0x5F5A); - named_labels = weak_label(named_labels, "_spverr", 0x5F5E); - named_labels = weak_label(named_labels, "_spverrAddress", 0x5F60); - named_labels = weak_label(named_labels, "_trace", 0x5F64); - named_labels = weak_label(named_labels, "_traceAddress", 0x5F66); - named_labels = weak_label(named_labels, "_nocod0", 0x5F6A); - named_labels = weak_label(named_labels, "_nocod0Address", 0x5F6C); - named_labels = weak_label(named_labels, "_nocod0", 0x5F70); - named_labels = weak_label(named_labels, "_nocod0Address", 0x5F72); - named_labels = weak_label(named_labels, "_slevel1", 0x5F76); - named_labels = weak_label(named_labels, "_slevel1Address", 0x5F78); - named_labels = weak_label(named_labels, "_slevel2", 0x5F7C); - named_labels = weak_label(named_labels, "_slevel2Address", 0x5F7E); - named_labels = weak_label(named_labels, "_slevel3", 0x5F82); - named_labels = weak_label(named_labels, "_slevel3Address", 0x5F84); - named_labels = weak_label(named_labels, "WORD_RAM_2M", 0x80000); - named_labels = weak_label(named_labels, "WORD_RAM_1M", 0xC0000); - named_labels = weak_label(named_labels, "LED_CONTROL", 0xFFFF8000); - named_labels = weak_label(named_labels, "VERSION_RESET", 0xFFFF8001); - named_labels = weak_label(named_labels, "MEM_MODE_WORD", 0xFFFF8002); - named_labels = weak_label(named_labels, "MEM_MODE_BYTE", 0xFFFF8003); - named_labels = weak_label(named_labels, "CDC_CTRL", 0xFFFF8004); - named_labels = weak_label(named_labels, "CDC_AR", 0xFFFF8005); - named_labels = weak_label(named_labels, "CDC_REG_DATA_WORD", 0xFFFF8006); - named_labels = weak_label(named_labels, "CDC_REG_DATA", 0xFFFF8007); - named_labels = weak_label(named_labels, "CDC_HOST_DATA", 0xFFFF8008); - named_labels = weak_label(named_labels, "CDC_DMA_ADDR", 0xFFFF800A); - named_labels = weak_label(named_labels, "STOP_WATCH", 0xFFFF800C); - named_labels = weak_label(named_labels, "COMM_MAIN_FLAG", 0xFFFF800E); - named_labels = weak_label(named_labels, "COMM_SUB_FLAG", 0xFFFF800F); - named_labels = weak_label(named_labels, "COMM_CMD0", 0xFFFF8010); - named_labels = weak_label(named_labels, "COMM_CMD1", 0xFFFF8012); - named_labels = weak_label(named_labels, "COMM_CMD2", 0xFFFF8014); - named_labels = weak_label(named_labels, "COMM_CMD3", 0xFFFF8016); - named_labels = weak_label(named_labels, "COMM_CMD4", 0xFFFF8018); - named_labels = weak_label(named_labels, "COMM_CMD5", 0xFFFF801A); - named_labels = weak_label(named_labels, "COMM_CMD6", 0xFFFF801C); - named_labels = weak_label(named_labels, "COMM_CMD7", 0xFFFF801E); - named_labels = weak_label(named_labels, "COMM_STATUS0", 0xFFFF8020); - named_labels = weak_label(named_labels, "COMM_STATUS1", 0xFFFF8022); - named_labels = weak_label(named_labels, "COMM_STATUS2", 0xFFFF8024); - named_labels = weak_label(named_labels, "COMM_STATUS3", 0xFFFF8026); - named_labels = weak_label(named_labels, "COMM_STATUS4", 0xFFFF8028); - named_labels = weak_label(named_labels, "COMM_STATUS5", 0xFFFF802A); - named_labels = weak_label(named_labels, "COMM_STATUS6", 0xFFFF802C); - named_labels = weak_label(named_labels, "COMM_STATUS7", 0xFFFF802E); - named_labels = weak_label(named_labels, "TIMER_WORD", 0xFFFF8030); - named_labels = weak_label(named_labels, "TIMER", 0xFFFF8031); - named_labels = weak_label(named_labels, "INT_MASK_WORD", 0xFFFF8032); - named_labels = weak_label(named_labels, "INT_MASK", 0xFFFF8033); - named_labels = weak_label(named_labels, "CDD_FADER", 0xFFFF8034); - named_labels = weak_label(named_labels, "CDD_CTRL_WORD", 0xFFFF8036); - named_labels = weak_label(named_labels, "CDD_CTRL_BYTE", 0xFFFF8037); + add_segacd_subcpu_labels(context); } } uint32_t size, tmp_addr; @@ -594,57 +346,57 @@ .buffer = filebuf }; uint8_t valid_address; - while(def) { + while(context->deferred) { do { valid_address = 0; - address = def->address; - if (!is_visited(address)) { - address &= 0xFFFFFF; + address = context->deferred->address; + if (!is_visited(context, address)) { + address &= context->address_mask; if (address < address_end && address >= address_off) { valid_address = 1; + address = context->deferred->address; } } - tmpd = def; - def = def->next; + deferred_addr *tmpd = context->deferred; + context->deferred = context->deferred->next; free(tmpd); - } while(def && !valid_address); + } while(context->deferred && !valid_address); if (!valid_address) { break; } for(;;) { - if ((address & 0xFFFFFF) > address_end || address < address_off) { + if ((address & context->address_mask) > address_end || address < address_off) { break; } - visit(address); + visit(context, address); address = m68k_decode(fetch, &rom, &instbuf, address); //m68k_disasm(&instbuf, disbuf); //printf("%X: %s\n", instbuf.address, disbuf); - check_reference(&instbuf, &(instbuf.src)); - check_reference(&instbuf, &(instbuf.dst)); + check_reference(context, &instbuf, &(instbuf.src)); + check_reference(context, &instbuf, &(instbuf.dst)); if (instbuf.op == M68K_ILLEGAL || instbuf.op == M68K_RTS || instbuf.op == M68K_RTE || instbuf.op == M68K_INVALID) { break; } if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) { + tmp_addr = instbuf.address + 2 + instbuf.src.params.immed; + reference(context, tmp_addr); if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) { - address = instbuf.address + 2 + instbuf.src.params.immed; - reference(address); - if (is_visited(address)) { + address = tmp_addr; + if (is_visited(context, address)) { break; } } else { - tmp_addr = instbuf.address + 2 + instbuf.src.params.immed; - reference(tmp_addr); - def = defer(tmp_addr, def); + defer_disasm(context, tmp_addr); } } else if(instbuf.op == M68K_JMP) { if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { address = instbuf.src.params.immed; - if (is_visited(address)) { + if (is_visited(context, address)) { break; } } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { address = instbuf.src.params.regs.displacement + instbuf.address + 2; - if (is_visited(address)) { + if (is_visited(context, address)) { break; } } else { @@ -652,61 +404,32 @@ } } else if(instbuf.op == M68K_JSR) { if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) { - def = defer(instbuf.src.params.immed, def); + defer_disasm(context, instbuf.src.params.immed); } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) { - def = defer(instbuf.src.params.regs.displacement + instbuf.address + 2, def); + defer_disasm(context, instbuf.src.params.regs.displacement + instbuf.address + 2); } } } } if (labels) { - for (address = 0; address < address_off; address++) { - if (is_label(address)) { - char key[MAX_INT_KEY_SIZE]; - tern_int_key(address, key); - label_names *names = tern_find_ptr(named_labels, key); - if (names) { - for (int i = 0; i < names->num_labels; i++) - { - printf("%s equ $%X\n", names->labels[i], address); - } - } else { - printf("ADR_%X equ $%X\n", address, address); - } - } - } - for (address = address_end; address < (16*1024*1024); address++) { - if (is_label(address)) { - char key[MAX_INT_KEY_SIZE]; - tern_int_key(address, key); - label_names *names = tern_find_ptr(named_labels, key); - if (names) { - for (int i = 0; i < names->num_labels; i++) - { - printf("%s equ $%X\n", names->labels[i], names->full_address); - } - } else { - printf("ADR_%X equ $%X\n", address, address); - } - } - } + tern_foreach(context->labels, print_label_def, &rom); puts(""); } for (address = address_off; address < address_end; address+=2) { - if (is_visited(address)) { + if (is_visited(context, address)) { m68k_decode(fetch, &rom, &instbuf, address); if (labels) { - m68k_disasm_labels(&instbuf, disbuf, label_fun, named_labels); - char keybuf[MAX_INT_KEY_SIZE]; - label_names * names = tern_find_ptr(named_labels, tern_int_key(address, keybuf)); - if (names) - { - for (int i = 0; i < names->num_labels; i++) - { - printf("%s:\n", names->labels[i]); + m68k_disasm_labels(&instbuf, disbuf, label_fun, context); + label_def *label = find_label(context, address); + if (label) { + if (label->num_labels) { + for (int i = 0; i < label->num_labels; i++) + { + printf("%s:\n", label->labels[i]); + } + } else { + printf("ADR_%X:\n", label->full_address); } - } else if (is_label(instbuf.address)) { - printf("ADR_%X:\n", instbuf.address); } if (addr) { printf("\t%s\t;%X\n", disbuf, instbuf.address); diff -r 90297f1fb3fe -r 4c265d2f6c88 disasm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/disasm.c Sat Aug 27 17:07:57 2022 -0700 @@ -0,0 +1,294 @@ +#include "disasm.h" + +label_def *find_label(disasm_context *context, uint32_t address) +{ + char key[MAX_INT_KEY_SIZE]; + tern_int_key(address & context->address_mask, key); + return tern_find_ptr(context->labels, key); +} + +label_def *add_find_label(disasm_context *context, uint32_t address) +{ + char key[MAX_INT_KEY_SIZE]; + tern_int_key(address & context->address_mask, key); + label_def *def = tern_find_ptr(context->labels, key); + if (!def) + { + def = calloc(1, sizeof(label_def)); + context->labels = tern_insert_ptr(context->labels, key, def); + } + def->full_address = address; + return def; +} + +void weak_label(disasm_context *context, const char *name, uint32_t address) +{ + label_def *def = add_find_label(context, address); + if (def->num_labels == def->storage) { + def->storage = def->storage ? def->storage * 2 : 4; + def->labels = realloc(def->labels, def->storage * sizeof(char*));; + } + def->labels[def->num_labels++] = strdup(name); +} + +void reference(disasm_context *context, uint32_t address) +{ + label_def *def = add_find_label(context, address); + def->referenced = 1; +} + +void add_label(disasm_context *context, const char *name, uint32_t address) +{ + reference(context, address);; + weak_label(context, name, address); +} + +void visit(disasm_context *context, uint32_t address) +{ + if (!context->visited) { + uint32_t size = context->address_mask + 1; + size >>= context->visit_preshift; + size >>= 3; + context->visited = calloc(1, size); + } + address &= context->address_mask; + address >>= context->visit_preshift; + context->visited[address >> 3] |= 1 << (address & 7); +} + +uint8_t is_visited(disasm_context *context, uint32_t address) +{ + if (!context->visited) { + return 0; + } + address &= context->address_mask; + address >>= context->visit_preshift; + return (context->visited[address >> 3] & (1 << (address & 7))) != 0; +} + +void defer_disasm(disasm_context *context, uint32_t address) +{ + if (is_visited(context, address) || address & context->invalid_inst_addr_mask) { + return; + } + context->deferred = defer_address(context->deferred, address, NULL); +} + +void process_m68k_vectors(disasm_context *context, uint16_t *table, uint8_t labels_only) +{ + static const char* names[] = { + "access_fault", + "address_error", + "illegal_instruction", + "integer_divide_by_zero", + "chk_exception", + "trap_exception", + "privilege_violation", + "trace_exception", + "line_1010_emulator", + "line_1111_emulator" + }; + uint32_t address = table[2] << 16 | table[3]; + add_label(context, "start", address); + if (!labels_only) { + defer_disasm(context, address); + } + for (int i = 0; i < sizeof(names)/sizeof(*names); i++) + { + address = table[i*2+4] << 16 | table[i*2 + 5]; + add_label(context, names[i], address); + if (!labels_only) { + defer_disasm(context, address); + } + } + char int_name[] = "int_0"; + for (int i = 0; i < 7; i++) + { + int_name[4] = '1' + i; + address = table[i*2+50] << 16 | table[i*2 + 51]; + add_label(context, int_name, address); + if (!labels_only) { + defer_disasm(context, address); + } + } + + char trap_name[] = "trap_0"; + for (int i = 0; i < 16; i++) + { + trap_name[5] = i < 0xA ? '0' + i : 'a' + i - 0xA; + address = table[i*2+50] << 16 | table[i*2 + 51]; + add_label(context, trap_name, address); + if (!labels_only) { + defer_disasm(context, address); + } + } +} + +void add_segacd_maincpu_labels(disasm_context *context) +{ + weak_label(context, "_bios_reset", 0x280); + weak_label(context, "_bios_entry", 0x284); + weak_label(context, "_bios_init", 0x288); + weak_label(context, "_bios_init_sp", 0x28C); + weak_label(context, "_bios_vint", 0x290); + weak_label(context, "_bios_set_hint", 0x294); + weak_label(context, "_bios_poll_io", 0x298); + weak_label(context, "_bios_detect_io", 0x29C); + weak_label(context, "_bios_clear_vram", 0x2A0); + weak_label(context, "_bios_clear_nmtbl", 0x2A4); + weak_label(context, "_bios_clear_vsram", 0x2A8); + weak_label(context, "_bios_init_vdp", 0x2AC); + weak_label(context, "_bios_vdp_loadregs", 0x2B0); + weak_label(context, "_bios_vdp_fill", 0x2B4); + weak_label(context, "_bios_clear_vram_range", 0x2B8); + weak_label(context, "_bios_clear_vram_range_dma", 0x2BC); + weak_label(context, "_bios_vram_dma_fill", 0x2C0); + weak_label(context, "_bios_update_nmtbl", 0x2C4); + weak_label(context, "_bios_update_nmtbl_template", 0x2C8); + weak_label(context, "_bios_fill_nmtbl", 0x2CC); + weak_label(context, "_bios_vdp_dma", 0x2D0); + weak_label(context, "_bios_vdp_dma_wordram", 0x2D4); + weak_label(context, "_bios_vdp_display_enable", 0x2D8); + weak_label(context, "_bios_vdp_display_disable", 0x2DC); + weak_label(context, "_bios_pal_buffer", 0x2E0); + weak_label(context, "_bios_pal_buffer_update", 0x2E4); + weak_label(context, "_bios_pal_dma", 0x2E8); + weak_label(context, "_bios_gfx_decomp", 0x2EC); + weak_label(context, "_bios_gfx_decomp_ram", 0x2F0); + weak_label(context, "_bios_update_sprites", 0x2F4); + weak_label(context, "_bios_clear_ram", 0x2F8); + weak_label(context, "_bios_display_sprite", 0x300); + weak_label(context, "_bios_wait_vint", 0x304); + weak_label(context, "_bios_wait_vint_flags", 0x308); + weak_label(context, "_bios_dma_sat", 0x30C); + weak_label(context, "_bios_set_hint_direct", 0x314); + weak_label(context, "_bios_disable_hint", 0x318); + weak_label(context, "_bios_print", 0x31C); + weak_label(context, "_bios_load_user_font", 0x320); + weak_label(context, "_bios_load_bios_font", 0x324); + weak_label(context, "_bios_load_bios_font_default", 0x328); + //TODO: more functions in the middle here + weak_label(context, "_bios_prng_mod", 0x338); + weak_label(context, "_bios_prng", 0x33C); + weak_label(context, "_bios_clear_comm", 0x340); + weak_label(context, "_bios_comm_update", 0x344); + //TODO: more functions in the middle here + weak_label(context, "_bios_sega_logo", 0x364); + weak_label(context, "_bios_set_vint", 0x368); + //TODO: more functions at the end here + + weak_label(context, "WORD_RAM", 0x200000); + weak_label(context, "CD_RESET_IFL2", 0xA12000); + weak_label(context, "CD_RESET_IFL2_BYTE", 0xA12001); + weak_label(context, "CD_WRITE_PROTECT", 0xA12002); + weak_label(context, "CD_MEM_MODE", 0xA12003); + weak_label(context, "CDC_CTRL", 0xA12004); + weak_label(context, "HINT_VECTOR", 0xA12006); + weak_label(context, "CDC_HOST_DATA", 0xA12008); + weak_label(context, "STOP_WATCH", 0xA1200C); + weak_label(context, "COMM_MAIN_FLAG", 0xA1200E); + weak_label(context, "COMM_SUB_FLAG", 0xA1200F); + weak_label(context, "COMM_CMD0", 0xA12010); + weak_label(context, "COMM_CMD1", 0xA12012); + weak_label(context, "COMM_CMD2", 0xA12014); + weak_label(context, "COMM_CMD3", 0xA12016); + weak_label(context, "COMM_CMD4", 0xA12018); + weak_label(context, "COMM_CMD5", 0xA1201A); + weak_label(context, "COMM_CMD6", 0xA1201C); + weak_label(context, "COMM_CMD7", 0xA1201E); + weak_label(context, "COMM_STATUS0", 0xA12020); + weak_label(context, "COMM_STATUS1", 0xA12022); + weak_label(context, "COMM_STATUS2", 0xA12024); + weak_label(context, "COMM_STATUS3", 0xA12026); + weak_label(context, "COMM_STATUS4", 0xA12028); + weak_label(context, "COMM_STATUS5", 0xA1202A); + weak_label(context, "COMM_STATUS6", 0xA1202C); + weak_label(context, "COMM_STATUS7", 0xA1202E); +} + +void add_segacd_subcpu_labels(disasm_context *context) +{ + weak_label(context, "bios_common_work", 0x5E80); + weak_label(context, "_setjmptbl", 0x5F0A); + weak_label(context, "_waitvsync", 0x5F10); + weak_label(context, "_buram", 0x5F16); + weak_label(context, "_cdboot", 0x5F1C); + weak_label(context, "_cdbios", 0x5F22); + weak_label(context, "_usercall0", 0x5F28); + weak_label(context, "_usercall1", 0x5F2E); + weak_label(context, "_usercall2", 0x5F34); + weak_label(context, "_usercall2Address", 0x5F36); + weak_label(context, "_usercall3", 0x5F3A); + weak_label(context, "_adrerr", 0x5F40); + weak_label(context, "_adrerrAddress", 0x5F42); + weak_label(context, "_coderr", 0x5F46); + weak_label(context, "_coderrAddress", 0x5F48); + weak_label(context, "_diverr", 0x5F4C); + weak_label(context, "_diverrAddress", 0x5F4E); + weak_label(context, "_chkerr", 0x5F52); + weak_label(context, "_chkerrAddress", 0x5F54); + weak_label(context, "_trperr", 0x5F58); + weak_label(context, "_trperrAddress", 0x5F5A); + weak_label(context, "_spverr", 0x5F5E); + weak_label(context, "_spverrAddress", 0x5F60); + weak_label(context, "_trace", 0x5F64); + weak_label(context, "_traceAddress", 0x5F66); + weak_label(context, "_nocod0", 0x5F6A); + weak_label(context, "_nocod0Address", 0x5F6C); + weak_label(context, "_nocod0", 0x5F70); + weak_label(context, "_nocod0Address", 0x5F72); + weak_label(context, "_slevel1", 0x5F76); + weak_label(context, "_slevel1Address", 0x5F78); + weak_label(context, "_slevel2", 0x5F7C); + weak_label(context, "_slevel2Address", 0x5F7E); + weak_label(context, "_slevel3", 0x5F82); + weak_label(context, "_slevel3Address", 0x5F84); + weak_label(context, "WORD_RAM_2M", 0x80000); + weak_label(context, "WORD_RAM_1M", 0xC0000); + weak_label(context, "LED_CONTROL", 0xFFFF8000); + weak_label(context, "VERSION_RESET", 0xFFFF8001); + weak_label(context, "MEM_MODE_WORD", 0xFFFF8002); + weak_label(context, "MEM_MODE_BYTE", 0xFFFF8003); + weak_label(context, "CDC_CTRL", 0xFFFF8004); + weak_label(context, "CDC_AR", 0xFFFF8005); + weak_label(context, "CDC_REG_DATA_WORD", 0xFFFF8006); + weak_label(context, "CDC_REG_DATA", 0xFFFF8007); + weak_label(context, "CDC_HOST_DATA", 0xFFFF8008); + weak_label(context, "CDC_DMA_ADDR", 0xFFFF800A); + weak_label(context, "STOP_WATCH", 0xFFFF800C); + weak_label(context, "COMM_MAIN_FLAG", 0xFFFF800E); + weak_label(context, "COMM_SUB_FLAG", 0xFFFF800F); + weak_label(context, "COMM_CMD0", 0xFFFF8010); + weak_label(context, "COMM_CMD1", 0xFFFF8012); + weak_label(context, "COMM_CMD2", 0xFFFF8014); + weak_label(context, "COMM_CMD3", 0xFFFF8016); + weak_label(context, "COMM_CMD4", 0xFFFF8018); + weak_label(context, "COMM_CMD5", 0xFFFF801A); + weak_label(context, "COMM_CMD6", 0xFFFF801C); + weak_label(context, "COMM_CMD7", 0xFFFF801E); + weak_label(context, "COMM_STATUS0", 0xFFFF8020); + weak_label(context, "COMM_STATUS1", 0xFFFF8022); + weak_label(context, "COMM_STATUS2", 0xFFFF8024); + weak_label(context, "COMM_STATUS3", 0xFFFF8026); + weak_label(context, "COMM_STATUS4", 0xFFFF8028); + weak_label(context, "COMM_STATUS5", 0xFFFF802A); + weak_label(context, "COMM_STATUS6", 0xFFFF802C); + weak_label(context, "COMM_STATUS7", 0xFFFF802E); + weak_label(context, "TIMER_WORD", 0xFFFF8030); + weak_label(context, "TIMER", 0xFFFF8031); + weak_label(context, "INT_MASK_WORD", 0xFFFF8032); + weak_label(context, "INT_MASK", 0xFFFF8033); + weak_label(context, "CDD_FADER", 0xFFFF8034); + weak_label(context, "CDD_CTRL_WORD", 0xFFFF8036); + weak_label(context, "CDD_CTRL_BYTE", 0xFFFF8037); +} + +disasm_context *create_68000_disasm(void) +{ + disasm_context *context = calloc(1, sizeof(disasm_context)); + context->address_mask = 0xFFFFFF; + context->invalid_inst_addr_mask = 1; + context->visit_preshift = 1; + return context; +} + diff -r 90297f1fb3fe -r 4c265d2f6c88 disasm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/disasm.h Sat Aug 27 17:07:57 2022 -0700 @@ -0,0 +1,37 @@ +#ifndef DISASM_H_ +#define DISASM_H_ + +#include +#include "tern.h" +#include "backend.h" + +typedef struct { + char **labels; + uint32_t num_labels; + uint32_t storage; + uint32_t full_address; + uint8_t referenced; +} label_def; + +typedef struct { + tern_node *labels; + uint8_t *visited; + deferred_addr *deferred; + uint32_t address_mask; + uint32_t invalid_inst_addr_mask; + uint32_t visit_preshift; +} disasm_context; + +label_def *find_label(disasm_context *context, uint32_t address); +void weak_label(disasm_context *context, const char *name, uint32_t address); +void reference(disasm_context *context, uint32_t address); +void add_label(disasm_context *context, const char *name, uint32_t address); +void visit(disasm_context *context, uint32_t address); +uint8_t is_visited(disasm_context *context, uint32_t address); +void defer_disasm(disasm_context *context, uint32_t address); +void process_m68k_vectors(disasm_context *context, uint16_t *table, uint8_t labels_only); +void add_segacd_maincpu_labels(disasm_context *context); +void add_segacd_subcpu_labels(disasm_context *context); +disasm_context *create_68000_disasm(void); + +#endif //DISASM_H_