debugger - add toolcall and GS/OS call recognition to the disassembler.

This commit is contained in:
Kelvin Sherlock 2019-02-16 17:29:39 -05:00
parent a65833d6d8
commit 9589abfda7
5 changed files with 1962 additions and 108 deletions

View File

@ -140,6 +140,8 @@ add_executable(GSplus WIN32 MACOSX_BUNDLE
$<$<BOOL:${WIN32}>:win32.rc>
$<$<BOOL:${APPLE}>:assets/gsp_icon.icns>
$<$<BOOL:${APPLE}>:assets/GSBug.Templates>
$<$<BOOL:${APPLE}>:assets/Tools.text>
$<$<BOOL:${APPLE}>:assets/GSOS.text>
$<$<BOOL:${APPLE}>:fix_mac_menu.m>
)
@ -152,6 +154,8 @@ SET_SOURCE_FILES_PROPERTIES(
SET_SOURCE_FILES_PROPERTIES(
assets/GSBug.Templates
assets/Tools.text
assets/GSOS.text
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)

120
src/assets/GSOS.text Normal file
View File

@ -0,0 +1,120 @@
; ProDOS 16 Calls.
0001 CREATE
0002 DESTROY
0004 CHANGE_PATH
0005 SET_FILE_INFO
0006 GET_FILE_INFO
0008 VOLUME
0009 SET_PREFIX
000A GET_PREFIX
000B CLEAR_BACKUP_BIT
0010 OPEN
0011 NEWLINE
0012 READ
0013 WRITE
0014 CLOSE
0015 FLUSH
0016 SET_MARK
0017 GET_MARK
0018 SET_EOF
0019 GET_EOF
001A SET_LEVEL
001B GET_LEVEL
001C GET_DIR_ENTRY
0020 GET_DEV_NUM
0021 GET_LAST_DEV
0022 READ_BLOCK
0023 WRITE_BLOCK
0024 FORMAT
0025 ERASE_DISK
0027 GET_NAME
0028 GET_BOOT_VOL
0029 QUIT
002A GET_VERSION
002C D_INFO
0031 ALLOC_INTERRUPT
0032 DEALLOCATE_INTERRUPT
; ORCA/Shell calls.
0101 Get_LInfo
0102 Set_LInfo
0103 Get_Lang
0104 Set_Lang
0105 Error
0106 Set_Variable
0107 Version
0108 Read_Indexed
0109 Init_Wildcard
010A Next_Wildcard
010B Read_Variable
010C ChangeVector
010D Execute
010E FastFile
010F Direction
0110 Redirect
0113 Stop
0114 ExpandDevices
0115 UnsetVariable
0116 Export
0117 PopVariables
0118 PushVariables
0119 SetStopFlag
011A ConsoleOut
011B SetIODevices
011C GetIODevices
011D GetCommand
; GS/OS Calls.
2001 Create
2002 Destroy
2003 OSShutdown
2004 ChangePath
2005 SetFileInfo
2006 GetFileInfo
2007 JudgeName
2008 Volume
2009 SetPrefix
200A GetPrefix
200B ClearBackup
200C SetSysPrefs
200D Null
200E ExpandPath
200F GetSysPrefs
2010 Open
2011 NewLine
2012 Read
2013 Write
2014 Close
2015 Flush
2016 SetMark
2017 GetMark
2018 SetEOF
2019 GetEOF
201A SetLevel
201B GetLevel
201C GetDirEntry
201D BeginSession
201E EndSession
201F SessionStatus
2020 GetDevNumber
2024 Format
2025 EraseDisk
2026 ResetCache
2027 GetName
2028 GetBootvol
2029 Quit
202A GetVersion
202B GetFSTInfo
202C DInfo
202D DStatus
202E DControl
202F DRead
2030 DWrite
2031 BindInt
2032 UnbindInt
2033 FSTSpecific
2034 AddNotifyProc
2035 DelNotifyProc
2036 DRename
2037 GetStdRefNum
2038 GetRefNum
2039 GetRefInfo
203A SetStdRefNum

1460
src/assets/Tools.text Normal file

File diff suppressed because it is too large Load Diff

View File

@ -44,8 +44,10 @@ static word32 g_prev_stack_bank = 0;
static int g_templates_loaded = 0;
extern void debug_load_template(const char *path);
extern void debug_load_templates(const char *path);
extern word32 debug_apply_template(word32 address, const char *name);
extern void debug_load_tools(const char *path, unsigned vector);
extern const char *debug_tool_name(unsigned, unsigned vector);
#if defined(__APPLE__)
#include <mach-o/dyld.h>
@ -267,42 +269,90 @@ word32 do_stack(word32 address, unsigned bank) {
}
word32 do_list(word32 address, int *psr_ptr, int lines) {
struct disasm_cookie {
unsigned psr;
unsigned x;
};
static int is_jsl_e10000(word32 address) {
return get_memory_c(address, 0) == 0x22 &&
get_memory24_c(address + 1, 0) == 0xe10000;
}
static int is_jsl_e10008(word32 address) {
return get_memory_c(address, 0) == 0x22 &&
get_memory24_c(address + 1, 0) == 0xe10008;
}
static int is_jsl_e100a8(word32 address) {
return get_memory_c(address, 0) == 0x22 &&
get_memory24_c(address + 1, 0) == 0xe100a8;
}
static int is_jsl_e100b0(word32 address) {
return get_memory_c(address, 0) == 0x22 &&
get_memory24_c(address + 1, 0) == 0xe100b0;
}
static int is_jsr_bf00(word32 address) {
return get_memory_c(address, 0) == 0x20 &&
get_memory16_c(address + 1, 0) == 0xbf00;
}
static int g_disasm_psr;
word32 do_list(word32 address, int lines) {
unsigned char buffer2[32];
char buffer[32];
int psr = *psr_ptr;
const char *opcode_string;
unsigned opcode;
unsigned dtype;
unsigned operand;
word32 pc;
int i;
int args;
int n;
while (lines--) {
int bsize = 0;
pc = address;
opcode = get_memory_c(address++, 0);
dtype = disasm_types[opcode];
args = dtype >> 8;
buffer2[bsize++] = opcode;
opcode_string = disasm_opcodes[opcode];
switch (args) {
case 4:
args = psr & 0x20 ? 1 : 2;
args = g_disasm_psr & 0x20 ? 1 : 2;
break;
case 5:
args = psr & 0x10 ? 1 : 2;
args = g_disasm_psr & 0x10 ? 1 : 2;
break;
}
operand = 0;
switch(args) {
case 1:
operand = get_memory_c(address, 0);
buffer2[bsize++] = operand;
break;
case 2:
operand = get_memory16_c(address, 0);
buffer2[bsize++] = operand;
buffer2[bsize++] = operand >> 8;
break;
case 3:
operand = get_memory24_c(address, 0);
buffer2[bsize++] = operand;
buffer2[bsize++] = operand >> 8;
buffer2[bsize++] = operand >> 16;
break;
}
address += args;
@ -319,91 +369,141 @@ word32 do_list(word32 address, int *psr_ptr, int lines) {
sprintf(buffer, "$%04x,y", operand);
break;
case ABSIND:
sprintf(buffer,"($%04x)",operand );
break;
case ABSXIND:
sprintf(buffer,"($%04x,x)",operand );
break;
case IMPLY:
break;
case ACCUM:
break;
case IMMED:
sprintf(buffer,"#$%0*x",args * 2, operand);
break;
case JUST8:
sprintf(buffer,"$%02x",operand);
break;
case DLOC:
sprintf(buffer,"$%02x",operand);
break;
case DLOCX:
sprintf(buffer,"$%02x,x",operand);
break;
case DLOCY:
sprintf(buffer,"$%02x,y",operand);
break;
case ABSLONG:
sprintf(buffer,"$%06x",operand);
break;
case ABSLONGX:
sprintf(buffer,"$%06x,x",operand);
break;
case DLOCIND:
sprintf(buffer,"($%02x)",operand);
break;
case DLOCINDY:
sprintf(buffer,"($%02x),y",operand);
break;
case DLOCXIND:
sprintf(buffer,"($%02x,x)",operand);
break;
case DLOCBRAK:
sprintf(buffer,"[$%02x]",operand);
break;
case DLOCBRAKY:
sprintf(buffer,"[$%02x],y",operand);
break;
case DISP8:
sprintf(buffer,"$%04x",
(address+(int8_t)operand) & 0xffff);
break;
case DISP8S:
sprintf(buffer,"$%02x,s",operand);
break;
case DISP8SINDY:
sprintf(buffer,"($%02x,s),y",operand);
break;
case DISP16:
sprintf(buffer,"$%04x",
(address+(int16_t)(operand)) & 0xffff);
break;
case MVPMVN:
sprintf(buffer,"$%02x,$%02x",operand & 0xff,operand >> 8);
break;
case SEPVAL:
psr |= operand;
sprintf(buffer,"#$%02x",operand);
break;
case REPVAL:
psr &= ~operand;
sprintf(buffer,"#$%02x",operand);
break;
case ABSIND:
sprintf(buffer,"($%04x)",operand );
break;
case ABSXIND:
sprintf(buffer,"($%04x,x)",operand );
break;
case IMPLY:
break;
case ACCUM:
break;
case IMMED:
sprintf(buffer,"#$%0*x",args * 2, operand);
break;
case JUST8:
sprintf(buffer,"$%02x",operand);
break;
case DLOC:
sprintf(buffer,"$%02x",operand);
break;
case DLOCX:
sprintf(buffer,"$%02x,x",operand);
break;
case DLOCY:
sprintf(buffer,"$%02x,y",operand);
break;
case ABSLONG:
sprintf(buffer,"$%06x",operand);
break;
case ABSLONGX:
sprintf(buffer,"$%06x,x",operand);
break;
case DLOCIND:
sprintf(buffer,"($%02x)",operand);
break;
case DLOCINDY:
sprintf(buffer,"($%02x),y",operand);
break;
case DLOCXIND:
sprintf(buffer,"($%02x,x)",operand);
break;
case DLOCBRAK:
sprintf(buffer,"[$%02x]",operand);
break;
case DLOCBRAKY:
sprintf(buffer,"[$%02x],y",operand);
break;
case DISP8:
sprintf(buffer,"$%04x",
(address+(int8_t)operand) & 0xffff);
break;
case DISP8S:
sprintf(buffer,"$%02x,s",operand);
break;
case DISP8SINDY:
sprintf(buffer,"($%02x,s),y",operand);
break;
case DISP16:
sprintf(buffer,"$%04x",
(address+(int16_t)(operand)) & 0xffff);
break;
case MVPMVN:
sprintf(buffer,"$%02x,$%02x",operand & 0xff,operand >> 8);
break;
case SEPVAL:
case REPVAL:
sprintf(buffer,"#$%02x",operand);
break;
}
printf("%02x/%04x: %s %-10s",
pc >> 16, pc & 0xffff,
disasm_opcodes[opcode], buffer);
/* todo -- special case for ldx #xxxx, jsl $e10000 */
/* todo -- special case for GS/OS calls */
/* todo -- special case for P8 MLI calls */
printf("%02x", opcode);
for(i = 0 ; i < args; ++i) {
printf(" %02x", operand & 0xff);
operand >>= 8;
switch (opcode) {
case 0xe2: /* sep */
g_disasm_psr|= operand;
break;
case 0xc2: /* rep */
g_disasm_psr &= ~operand;
break;
case 0xfb: /* xce */
g_disasm_psr |= 0x0130;
break;
case 0xa2: /* ldx # */
if (is_jsl_e10000(address)) {
/* tool call ... */
const char *name = debug_tool_name(operand, 0xe10000);
if (name) {
opcode_string = name;
buffer[0] = 0;
for (i = 0; i < 4; ++i) {
buffer2[bsize++] = get_memory_c(address++, 0);
}
}
}
break;
case 0xae: /* ldx ... */
case 0xbe:
case 0xa6:
case 0xb6:
case 0xfa: /* plx */
case 0xaa: /* tax */
case 0xba: /* tsx */
case 0xbb: /* tyx */
case 0xca: /* dex */
case 0xe8: /* inx */
break;
case 0x22: /* jsl */
if (operand == 0xe100a8) {
/* inline GS/OS call? */
unsigned num = get_memory16_c(address, 0);
const char *name = debug_tool_name(num, operand);
if (name) {
opcode_string = name;
unsigned parms = get_memory24_c(address + 2, 0);
sprintf(buffer, "$%06x", parms);
for (i = 0; i < 6; ++i) {
buffer2[bsize++] = get_memory_c(address++, 0);
}
}
}
break;
}
n = printf("%02x/%04x: %s %s",
pc >> 16, pc & 0xffff,
opcode_string, buffer);
for(; n < 40; ++n) putchar(' ');
for(i = 0; i < bsize; ++i) {
printf(" %02x", buffer2[i]);
}
fputc('\n', stdout);
}
*psr_ptr = psr;
return address;
}
@ -729,24 +829,26 @@ void delete_bp(int type, word32 addr) {
static void do_help(void) {
fputs(
" * Print registers\n"
" reg=value Assign register (a,x,y,etc)\n"
" reset Reset computer\n"
" quit exit debugger\n"
" s single step\n"
" g go\n"
" bp List PC breakpoints\n"
" mp List memory breakpoints\n"
" * Print registers\n"
" reg=value Assign register (a,x,y,etc)\n"
" reset Reset computer\n"
" quit Exit debugger\n"
" s Single step\n"
" g Go\n"
" bp List PC breakpoints\n"
" mp List memory breakpoints\n"
"\n"
" [address];l List\n"
" [address];h Hexdump\n"
" [address];bp Set PC breakpoint\n"
" [address];bp- Remove PC breakpoint\n"
" [address];mp Set memory breakpoint\n"
" [address];mp- Remove memory breakpoint\n"
" [address];l List\n"
" [address];h Hexdump\n"
" [address];bp Set PC breakpoint\n"
" [address];bp- Remove PC breakpoint\n"
" [address];mp Set memory breakpoint\n"
" [address];mp- Remove memory breakpoint\n"
" [address]\\temp name Display template\n"
"\n"
"\n"
"Address = 12/3456, 123456, or 1234\n",
"Address = 12/3456, 123456, or 1234\n"
"Register = %%a, %%x, %%y, %%pc, etc\n",
stdout);
}
@ -757,8 +859,8 @@ static int parse_command(const char *cp) {
/* TODO:
pc++ EOL -> skip current instruction
! -> mini assembler mode.
require 2 successive ^Ds to exit
*/
const char *YYCURSOR = cp;
@ -946,8 +1048,7 @@ command:
}
(";l" | "l") eol {
int psr = engine.psr;
g_prev_address = do_list(addr, &psr, 20);
g_prev_address = do_list(addr, 20);
return 0;
}
";h" eol {
@ -1027,15 +1128,25 @@ int debug_shell(int code) {
int c;
char *cp;
int psr = engine.psr;
if (!g_templates_loaded) {
char *path;
g_templates_loaded = 1;
path = get_resource_path("GSBug.Templates");
debug_load_template(path);
free(path);
if (path) {
debug_load_templates(path);
free(path);
}
path = get_resource_path("Tools.text");
if (path) {
debug_load_tools(path, 0xe10000);
free(path);
}
path = get_resource_path("GSOS.text");
if (path) {
debug_load_tools(path, 0xe100a8);
free(path);
}
}
@ -1061,11 +1172,12 @@ int debug_shell(int code) {
/* halt_printf */
}
do_list(engine.kpc, &psr, 1);
g_prev_stack_address = engine.stack;
g_prev_stack_bank = engine.kpc & 0xff0000;
g_prev_address = engine.kpc;
g_disasm_psr = engine.psr;
do_list(engine.kpc, 1);
for(;;) {
cp = x_readline("> ");

View File

@ -16,6 +16,7 @@
re2c:yyfill:enable = 0;
eol = "\x00";
ws = [ \t\r\n];
x = [0-9a-fA-F];
*/
@ -142,7 +143,7 @@ next:
}
void debug_load_template(const char *path) {
void debug_load_templates(const char *path) {
FILE *f;
char buffer[1024];
int ok;
@ -312,3 +313,160 @@ word32 debug_apply_template(word32 address, const char *name) {
fputc('\n', stdout);
return address;
}
/* nifty list */
/*
* format:
* fffx ... header comments
* xxxx name ; p8 mli calls
* *
* xxxx name ; p16/gsos calls
* *
* xxxx name ; tool calls
* *
* xxxx name ; user tool calls
* *
* xxxx name ; e1 vectors
* *
* xxxx name ; e0 vectors
* *
* xxxx name ; softswitch/f8 rom
* *
* xxxx name ; 01 vectors
* *
* xxxx name ; nifty list service calls
* *
* xxxx name ; resource types
* *
* xxxx name ; error codes
* *
* xxxx name ; HC IIgs callbacks
* *
* xxxx name ; request codes
* *
*
*/
struct tool {
char *name;
unsigned number;
unsigned vector;
};
struct tool *tools = NULL;
int tool_count = 0;
int tool_alloc = 0;
static void add_tool(struct tool *t) {
if (tool_count == tool_alloc) {
size_t size = (tool_alloc + 1024) * sizeof(struct tool);
void *tmp = realloc(tools, size);
if (!tmp) return;
tools = tmp;
tool_alloc += 1024;
}
tools[tool_count++] = *t;
}
static word32 to_hex(const char *iter, const char *end) {
word32 rv = 0;
while(iter != end) {
char c = *iter++;
rv <<= 4;
if (isdigit(c)) rv |= c - '0';
else rv |= (c | 0x20) - 'a' + 10;
}
return rv;
}
static int tool_compare(const void *a, const void *b) {
const struct tool *aa = a;
const struct tool *bb = b;
int rv = (int)aa->vector - (int)bb->vector;
if (rv == 0)
rv = (int)aa->number - (int)bb->number;
return rv;
}
/*
static int tool_search(const void *a, const void *b) {
const struct tool *aa = a;
const struct tool *bb = b;
int rv = (int)aa->vector - (int)bb->vector
if (rv == 0)
rv = (int)aa->number - (int)bb->number;
return rv;
}
*/
void debug_load_tools(const char *path, unsigned vector) {
FILE *f;
char buffer[1024];
unsigned line = 0;
const char *YYMARKER = NULL;
const char *YYCTXMARKER = NULL;
f = fopen(path, "r");
if (!f) {
fprintf(stderr, "Unable to load %s: %s\n", path, strerror(errno));
return;
}
for (line = 1;;++line) {
const char *start;
const char *end;
struct tool tool = { 0, 0, vector };
const char *cp = fgets(buffer, sizeof(buffer), f);
if (!cp) break;
start = cp;
/*!re2c
[\r\n\x00] { continue; }
";" { continue; }
* {
fprintf(stderr, "%s:%d: Bad line: %s", path, line, buffer);
continue;
}
x{4} / ws { goto ok; }
*/
ok:
end = cp;
tool.number = to_hex(start, end);
while (isspace(*cp)) ++cp;
start = cp;
for(;;) {
/*!re2c
"" / (eol | ws) { break; }
* { continue; }
*/
}
end = cp;
if (end > start) {
int l = end - start;
/* add a leading _ */
tool.name = malloc(l + 2);
tool.name[0] = '_';
strncpy(tool.name + 1, start, l);
tool.name[l + 2] = 0;
add_tool(&tool);
}
}
qsort(tools, tool_count, sizeof(struct tool), tool_compare);
fclose(f);
}
const char *debug_tool_name(unsigned number, unsigned vector) {
struct tool tmp = { 0, number, vector };
struct tool *t = bsearch(&tmp, tools, tool_count, sizeof(struct tool), tool_compare);
if (t) return t->name;
return NULL;
}