From 89d8b3efcfde4f676e1e0ba964851050c8aaba13 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Fri, 5 Apr 2019 18:43:54 -0400 Subject: [PATCH] disassembler - inline debug name support. See IIgs technote #103. --- src/debug_shell.re2c | 125 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/src/debug_shell.re2c b/src/debug_shell.re2c index 72f41b5..469b53d 100644 --- a/src/debug_shell.re2c +++ b/src/debug_shell.re2c @@ -426,6 +426,63 @@ static int is_jsr_bf00(word32 address) { static int g_disasm_psr; +static const char *get_inline_debug_name(word32 address) { + static char buffer[256]; + + /* see IIgs technote #103 */ + /* 82 xx xx brl pastname + 71 77 + name + pastname: + */ + + /* uthernet uses bra ... tsk tsk. */ + + int match = 0; + int offset = 0; + + unsigned op = get_memory_c(address, 0); + if (op == 0x82 + && get_memory_c(address + 3, 0) == 0x71 + && get_memory_c(address + 4, 0) == 0x77) { + match = 1; + address += 5; + + offset = 3 + (int16_t)get_memory16_c(address + 1, 0); + offset &= 0xffff; + } + + if (op == 0x80 + && get_memory_c(address + 2, 0) == 0x71 + && get_memory_c(address + 3, 0) == 0x77) { + match = 1; + address += 4; + + offset = 2 + (int8_t)get_memory_c(address + 1, 0); + offset &= 0xffff; + + } + + + if (match) { + unsigned i, n; + + /* sanity check it offset */ + + n = get_memory_c(address++, 0); + for (i = 0; i < n; ++i) { + unsigned char c = get_memory_c(address++, 0); + if (c & 0x80) return NULL; + if (!isprint(c)) return NULL; + buffer[i] = c; + } + buffer[i] = 0; + return buffer; + } + + return NULL; +} + word32 do_list(word32 address, int lines) { unsigned char buffer2[32]; @@ -578,7 +635,7 @@ word32 do_list(word32 address, int lines) { comment = debug_tool_name(pc & 0xffff, bank); } - + uint32_t ea = 0; switch (opcode) { case 0xe2: /* sep */ g_disasm_psr|= operand; @@ -602,6 +659,7 @@ word32 do_list(word32 address, int lines) { } } break; +#if 0 case 0xae: /* ldx ... */ case 0xbe: case 0xa6: @@ -613,6 +671,7 @@ word32 do_list(word32 address, int lines) { case 0xca: /* dex */ case 0xe8: /* inx */ break; +#endif case 0x22: /* jsl */ if (operand == 0xe100a8) { /* inline GS/OS call? */ @@ -628,6 +687,8 @@ word32 do_list(word32 address, int lines) { buffer2[bsize++] = get_memory_c(address++, 0); } } + } else { + ea = operand; } break; case 0x20: /* jsr */ @@ -643,8 +704,70 @@ word32 do_list(word32 address, int lines) { buffer2[bsize++] = get_memory_c(address++, 0); } } + } else { + ea = (operand | (address & 0xff0000)); } break; + case 0x82: { + ea = address + (int16_t)operand; + ea &= 0xffff; + ea |= pc & 0xff0000; + + const char *name = get_inline_debug_name(pc); + /* start of an inline debug name? */ + if (name) { + opcode_string = name; + buffer[0] = 0; + + /* include the 0x77 71 magic bytes */ + for (i = 0; i < 2; ++i) { + buffer2[bsize++] = get_memory_c(address++, 0); + } + address = ea; + ea = 0; + } + break; + } + case 0x80: { + ea = address + (int8_t)operand; + ea &= 0xffff; + ea |= pc & 0xff0000; + + const char *name = get_inline_debug_name(pc); + /* start of an inline debug name? */ + if (name) { + opcode_string = name; + buffer[0] = 0; + + /* include the 0x77 71 magic bytes */ + for (i = 0; i < 2; ++i) { + buffer2[bsize++] = get_memory_c(address++, 0); + } + address = ea; + ea = 0; + } + break; + } + + + case 0x10: + case 0x30: + case 0x50: + case 0x70: + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: { + ea = address + (int8_t)operand; + ea &= 0xffff; + ea |= pc & 0xff0000; + break; + } + + } + + if (ea && !comment) { + comment = get_inline_debug_name(ea); } n = printf("%02x/%04x: %s %s",