Add a 'disassemble' command to the CP/M emulator.
This commit is contained in:
parent
d319c7d679
commit
22032575c5
2 changed files with 56 additions and 18 deletions
|
@ -343,24 +343,36 @@ static struct insn insns[0x100] =
|
||||||
|
|
||||||
uint16_t i8080_disassemble(char* buffer, size_t bufsiz, uint16_t pc)
|
uint16_t i8080_disassemble(char* buffer, size_t bufsiz, uint16_t pc)
|
||||||
{
|
{
|
||||||
uint8_t opcode = i8080_read(pc++);
|
uint8_t opcode = i8080_read(pc);
|
||||||
|
uint8_t p1 = i8080_read(pc+1);
|
||||||
|
uint8_t p2 = i8080_read(pc+2);
|
||||||
struct insn* insn = &insns[opcode];
|
struct insn* insn = &insns[opcode];
|
||||||
uint16_t value = 0;
|
uint16_t value = 0;
|
||||||
|
const char* left = "";
|
||||||
|
|
||||||
|
snprintf(buffer, bufsiz, "%04x : ", pc);
|
||||||
|
pc++;
|
||||||
|
|
||||||
switch (insn->operand)
|
switch (insn->operand)
|
||||||
{
|
{
|
||||||
case NOTHING:
|
case NOTHING:
|
||||||
|
left = "%02x : ";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONST8:
|
case CONST8:
|
||||||
value = i8080_read(pc++);
|
left = "%02x %02x : ";
|
||||||
|
value = p1;
|
||||||
|
pc++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONST16:
|
case CONST16:
|
||||||
value = i8080_read(pc++);
|
left = "%02x %02x %02x : ";
|
||||||
value |= i8080_read(pc++) << 8;
|
value = p1 | (p2<<8);
|
||||||
|
pc += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buffer, bufsiz, insn->name, value);
|
snprintf(buffer + 7, bufsiz - 7, left, opcode, p1, p2);
|
||||||
|
snprintf(buffer + 18, bufsiz - 18, insn->name, value);
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ static bool tracing = false;
|
||||||
static bool singlestepping = true;
|
static bool singlestepping = true;
|
||||||
static bool bdosbreak = false;
|
static bool bdosbreak = false;
|
||||||
|
|
||||||
|
static const char* delimiters = " \t\n\r";
|
||||||
|
|
||||||
uint8_t i8080_read(uint16_t addr)
|
uint8_t i8080_read(uint16_t addr)
|
||||||
{
|
{
|
||||||
return ram[addr];
|
return ram[addr];
|
||||||
|
@ -65,13 +67,13 @@ void showregs(void)
|
||||||
int tstates;
|
int tstates;
|
||||||
uint16_t pc = i8080_read_reg16(PC);
|
uint16_t pc = i8080_read_reg16(PC);
|
||||||
i8080_disassemble(buffer, sizeof(buffer), pc);
|
i8080_disassemble(buffer, sizeof(buffer), pc);
|
||||||
printf("%04x : %s\n", pc, buffer);
|
puts(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_register(void)
|
static void cmd_register(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
char* w2 = strtok(NULL, " ");
|
char* w2 = strtok(NULL, delimiters);
|
||||||
|
|
||||||
if (w1 && w2)
|
if (w1 && w2)
|
||||||
{
|
{
|
||||||
|
@ -102,7 +104,7 @@ static void cmd_register(void)
|
||||||
|
|
||||||
static void cmd_break(void)
|
static void cmd_break(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
if (w1)
|
if (w1)
|
||||||
{
|
{
|
||||||
uint16_t breakpc = strtoul(w1, NULL, 16);
|
uint16_t breakpc = strtoul(w1, NULL, 16);
|
||||||
|
@ -128,7 +130,7 @@ static void cmd_break(void)
|
||||||
|
|
||||||
static void cmd_watch(void)
|
static void cmd_watch(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
if (w1)
|
if (w1)
|
||||||
{
|
{
|
||||||
uint16_t watchaddr = strtoul(w1, NULL, 16);
|
uint16_t watchaddr = strtoul(w1, NULL, 16);
|
||||||
|
@ -158,7 +160,7 @@ static void cmd_watch(void)
|
||||||
|
|
||||||
static void cmd_delete_breakpoint(void)
|
static void cmd_delete_breakpoint(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
if (w1)
|
if (w1)
|
||||||
{
|
{
|
||||||
uint16_t breakpc = strtoul(w1, NULL, 16);
|
uint16_t breakpc = strtoul(w1, NULL, 16);
|
||||||
|
@ -176,7 +178,7 @@ static void cmd_delete_breakpoint(void)
|
||||||
|
|
||||||
static void cmd_delete_watchpoint(void)
|
static void cmd_delete_watchpoint(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
if (w1)
|
if (w1)
|
||||||
{
|
{
|
||||||
uint16_t address = strtoul(w1, NULL, 16);
|
uint16_t address = strtoul(w1, NULL, 16);
|
||||||
|
@ -195,8 +197,8 @@ static void cmd_delete_watchpoint(void)
|
||||||
|
|
||||||
static void cmd_memory(void)
|
static void cmd_memory(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
char* w2 = strtok(NULL, " ");
|
char* w2 = strtok(NULL, delimiters);
|
||||||
|
|
||||||
if (!w2)
|
if (!w2)
|
||||||
w2 = "100";
|
w2 = "100";
|
||||||
|
@ -241,9 +243,30 @@ static void cmd_memory(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmd_unassemble(void)
|
||||||
|
{
|
||||||
|
char* w1 = strtok(NULL, delimiters);
|
||||||
|
char* w2 = strtok(NULL, delimiters);
|
||||||
|
uint16_t startaddr = i8080_read_reg16(PC);
|
||||||
|
uint16_t endaddr;
|
||||||
|
|
||||||
|
if (w1)
|
||||||
|
startaddr = strtoul(w1, NULL, 16);
|
||||||
|
endaddr = startaddr + 0x20;
|
||||||
|
if (w2)
|
||||||
|
endaddr = startaddr + strtoul(w2, NULL, 16);
|
||||||
|
|
||||||
|
while (startaddr < endaddr)
|
||||||
|
{
|
||||||
|
char buffer[80];
|
||||||
|
startaddr = i8080_disassemble(buffer, sizeof(buffer), startaddr);
|
||||||
|
puts(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void cmd_bdos(void)
|
static void cmd_bdos(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
if (w1)
|
if (w1)
|
||||||
bdosbreak = !!strtoul(w1, NULL, 16);
|
bdosbreak = !!strtoul(w1, NULL, 16);
|
||||||
else
|
else
|
||||||
|
@ -252,7 +275,7 @@ static void cmd_bdos(void)
|
||||||
|
|
||||||
static void cmd_tracing(void)
|
static void cmd_tracing(void)
|
||||||
{
|
{
|
||||||
char* w1 = strtok(NULL, " ");
|
char* w1 = strtok(NULL, delimiters);
|
||||||
if (w1)
|
if (w1)
|
||||||
tracing = !!strtoul(w1, NULL, 16);
|
tracing = !!strtoul(w1, NULL, 16);
|
||||||
else
|
else
|
||||||
|
@ -270,10 +293,11 @@ static void cmd_help(void)
|
||||||
" w <addr> set watchpoint\n"
|
" w <addr> set watchpoint\n"
|
||||||
" dw <addr> delete watchpoint\n"
|
" dw <addr> delete watchpoint\n"
|
||||||
" m <addr> <len> show memory\n"
|
" m <addr> <len> show memory\n"
|
||||||
|
" u <addr> <len> unassemble memory\n"
|
||||||
" s single step\n"
|
" s single step\n"
|
||||||
" g continue\n"
|
" g continue\n"
|
||||||
" bdos 0|1 enable break on bdos entry\n"
|
" bdos 0|1 enable break on bdos entry\n"
|
||||||
" trace 0|1 enable tracing\n"
|
" tracing 0|1 enable tracing\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +313,7 @@ static void debug(void)
|
||||||
if (!fgets(cmdline, sizeof(cmdline), stdin))
|
if (!fgets(cmdline, sizeof(cmdline), stdin))
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
char* token = strtok(cmdline, " \n\r\t");
|
char* token = strtok(cmdline, delimiters);
|
||||||
if (token != NULL)
|
if (token != NULL)
|
||||||
{
|
{
|
||||||
if (strcmp(token, "?") == 0)
|
if (strcmp(token, "?") == 0)
|
||||||
|
@ -306,6 +330,8 @@ static void debug(void)
|
||||||
cmd_delete_watchpoint();
|
cmd_delete_watchpoint();
|
||||||
else if (strcmp(token, "m") == 0)
|
else if (strcmp(token, "m") == 0)
|
||||||
cmd_memory();
|
cmd_memory();
|
||||||
|
else if (strcmp(token, "u") == 0)
|
||||||
|
cmd_unassemble();
|
||||||
else if (strcmp(token, "s") == 0)
|
else if (strcmp(token, "s") == 0)
|
||||||
{
|
{
|
||||||
singlestepping = true;
|
singlestepping = true;
|
||||||
|
|
Loading…
Add table
Reference in a new issue