diff disasm.c @ 2206:4c265d2f6c88

Minor refactor of 68K disassembler
author Michael Pavone <pavone@retrodev.com>
date Sat, 27 Aug 2022 17:07:57 -0700
parents
children de3d20e58555
line wrap: on
line diff
--- /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;
+}
+