mirror of
https://github.com/ksherlock/mpw.git
synced 2025-01-13 11:29:45 +00:00
debugger improvements
This commit is contained in:
parent
ba2fba246b
commit
03c0951253
206
bin/debugger.cpp
206
bin/debugger.cpp
@ -2,9 +2,12 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdlib>
|
#include <unordered_set>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
|
|
||||||
@ -13,9 +16,61 @@
|
|||||||
|
|
||||||
#include <debugger/commands.h>
|
#include <debugger/commands.h>
|
||||||
|
|
||||||
|
#include <cpu/defs.h>
|
||||||
|
#include <cpu/CpuModule.h>
|
||||||
|
|
||||||
|
#include <macos/traps.h>
|
||||||
|
#include <macos/sysequ.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void hexdump(const uint8_t *data, ssize_t size, uint32_t address = 0)
|
||||||
|
{
|
||||||
|
const char *HexMap = "0123456789abcdef";
|
||||||
|
|
||||||
|
char buffer1[16 * 3 + 1 + 1];
|
||||||
|
char buffer2[16 + 1];
|
||||||
|
ssize_t offset = 0;
|
||||||
|
unsigned i, j;
|
||||||
|
|
||||||
|
|
||||||
|
while(size > 0)
|
||||||
|
{
|
||||||
|
std::memset(buffer1, ' ', sizeof(buffer1));
|
||||||
|
std::memset(buffer2, ' ', sizeof(buffer2));
|
||||||
|
|
||||||
|
unsigned linelen = (unsigned)std::min(size, (ssize_t)16);
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < linelen; i++)
|
||||||
|
{
|
||||||
|
unsigned x = data[i];
|
||||||
|
buffer1[j++] = HexMap[x >> 4];
|
||||||
|
buffer1[j++] = HexMap[x & 0x0f];
|
||||||
|
j++;
|
||||||
|
if (i == 7) j++;
|
||||||
|
|
||||||
|
// isascii not part of std:: and may be a macro.
|
||||||
|
buffer2[i] = isascii(x) && std::isprint(x) ? x : '.';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer1[sizeof(buffer1)-1] = 0;
|
||||||
|
buffer2[sizeof(buffer2)-1] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
std::printf("%08x:\t%s\t%s\n", address + (unsigned)offset, buffer1, buffer2);
|
||||||
|
offset += 16;
|
||||||
|
data += 16;
|
||||||
|
size -= 16;
|
||||||
|
}
|
||||||
|
std::printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool ParseLine(const char *iter, Command *command);
|
bool ParseLine(const char *iter, Command *command);
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
uint32_t debuggerReadLong(uint32_t address)
|
uint32_t debuggerReadLong(uint32_t address)
|
||||||
@ -30,14 +85,34 @@ extern "C" {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t debuggerReadWord(uint32_t address)
|
||||||
|
{
|
||||||
|
uint16_t tmp = 0;
|
||||||
|
for (unsigned i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
if (address < Flags.memorySize)
|
||||||
|
tmp = (tmp << 8) + Flags.memory[address++];
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t debuggerReadByte(uint32_t address)
|
||||||
|
{
|
||||||
|
if (address < Flags.memorySize)
|
||||||
|
return Flags.memory[address];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugHelp(const Command &cmd)
|
void DebugHelp(const Command &cmd)
|
||||||
{
|
{
|
||||||
printf("help\n");
|
printf("help\n");
|
||||||
printf("break expression\n");
|
printf("break expression\n");
|
||||||
printf("step");
|
printf("step\n");
|
||||||
printf("continue");
|
printf("continue\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("print expression\n");
|
printf("print expression\n");
|
||||||
printf("list expression\n");
|
printf("list expression\n");
|
||||||
@ -64,56 +139,15 @@ void DebugPrint(const Command &cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hexdump(const uint8_t *data, ssize_t size, uint32_t address = 0)
|
|
||||||
{
|
|
||||||
const char *HexMap = "0123456789abcdef";
|
|
||||||
|
|
||||||
char buffer1[16 * 3 + 1 + 1];
|
|
||||||
char buffer2[16 + 1];
|
|
||||||
ssize_t offset = 0;
|
|
||||||
unsigned i, j;
|
|
||||||
|
|
||||||
|
|
||||||
while(size > 0)
|
|
||||||
{
|
|
||||||
std::memset(buffer1, ' ', sizeof(buffer1));
|
|
||||||
std::memset(buffer2, ' ', sizeof(buffer2));
|
|
||||||
|
|
||||||
unsigned linelen = (unsigned)std::min(size, (ssize_t)16);
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0, j = 0; i < linelen; i++)
|
|
||||||
{
|
|
||||||
unsigned x = data[i];
|
|
||||||
buffer1[j++] = HexMap[x >> 4];
|
|
||||||
buffer1[j++] = HexMap[x & 0x0f];
|
|
||||||
j++;
|
|
||||||
if (i == 7) j++;
|
|
||||||
|
|
||||||
// isascii not part of std:: and may be a macro.
|
|
||||||
buffer2[i] = isascii(x) && std::isprint(x) ? x : '.';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer1[sizeof(buffer1)-1] = 0;
|
|
||||||
buffer2[sizeof(buffer2)-1] = 0;
|
|
||||||
|
|
||||||
|
|
||||||
std::printf("%08x:\t%s\t%s\n", address + (unsigned)offset, buffer1, buffer2);
|
|
||||||
offset += 16;
|
|
||||||
data += 16;
|
|
||||||
size -= 16;
|
|
||||||
}
|
|
||||||
std::printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugDump(const Command &cmd)
|
void DebugDump(const Command &cmd)
|
||||||
{
|
{
|
||||||
// TODO -- if no address, use previous address.
|
// TODO -- if no address, use previous address.
|
||||||
|
// TODO -- support range?
|
||||||
if (cmd.argc == 1)
|
if (cmd.argc == 1)
|
||||||
{
|
{
|
||||||
uint32_t start = cmd.argv[0];
|
uint32_t start = cmd.argv[0];
|
||||||
if (start > Flags.memorySize) return;
|
if (start >= Flags.memorySize) return;
|
||||||
|
|
||||||
uint32_t end = std::min(start + 512, Flags.memorySize);
|
uint32_t end = std::min(start + 512, Flags.memorySize);
|
||||||
ssize_t size = end - start;
|
ssize_t size = end - start;
|
||||||
@ -123,6 +157,78 @@ void DebugDump(const Command &cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugList(const Command &cmd)
|
||||||
|
{
|
||||||
|
// TODO -- if no address, use previous address.
|
||||||
|
// TODO -- support range?
|
||||||
|
if (cmd.argc == 1)
|
||||||
|
{
|
||||||
|
uint32_t pc = cmd.argv[0];
|
||||||
|
if (pc & 0x01)
|
||||||
|
{
|
||||||
|
printf("address is not aligned: $%08x\n", pc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char strings[4][256];
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 32; ++i)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (pc >= Flags.memorySize) break;
|
||||||
|
|
||||||
|
uint16_t opcode = debuggerReadWord(pc);
|
||||||
|
|
||||||
|
if ((opcode & 0xf000) == 0xa000)
|
||||||
|
{
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = TrapName(opcode);
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
printf("$%08X %-51s ; %04X\n", pc, name, opcode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("$%08X Tool #$%04X ; %04X\n",
|
||||||
|
pc, opcode, opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
pc += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < 4; ++j) strings[j][0] = 0;
|
||||||
|
|
||||||
|
pc = cpuDisOpcode(pc, strings[0], strings[1], strings[2], strings[3]);
|
||||||
|
printf("%s %-10s %-40s ; %s\n", strings[0], strings[2], strings[3], strings[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DebugPrintRegisters(const Command &cmd)
|
||||||
|
{
|
||||||
|
printf("PC: %08X CSR: %04x\n", cpuGetPC(), cpuGetSR());
|
||||||
|
|
||||||
|
printf("D: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||||
|
cpuGetDReg(0), cpuGetDReg(1), cpuGetDReg(2), cpuGetDReg(3),
|
||||||
|
cpuGetDReg(4), cpuGetDReg(5), cpuGetDReg(6), cpuGetDReg(7)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
printf("A: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||||
|
cpuGetAReg(0), cpuGetAReg(1), cpuGetAReg(2), cpuGetAReg(3),
|
||||||
|
cpuGetAReg(4), cpuGetAReg(5), cpuGetAReg(6), cpuGetAReg(7)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo -- add sigint trap. it shall set a flag to break.
|
||||||
|
|
||||||
void DebugShell()
|
void DebugShell()
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
@ -156,6 +262,14 @@ void DebugShell()
|
|||||||
DebugDump(cmd);
|
DebugDump(cmd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case List:
|
||||||
|
DebugList(cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PrintRegisters:
|
||||||
|
DebugPrintRegisters(cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DebugHelp(cmd);
|
DebugHelp(cmd);
|
||||||
break;
|
break;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
enum {
|
enum {
|
||||||
Help,
|
Help,
|
||||||
Print,
|
Print,
|
||||||
|
PrintRegisters,
|
||||||
Dump,
|
Dump,
|
||||||
List,
|
List,
|
||||||
Break,
|
Break,
|
||||||
|
@ -262,6 +262,11 @@ bool ParseLine(const char *iter, Command *command)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
'l' | 'list' {
|
||||||
|
Parse(parser, tkLIST, 0, command);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
'n' | 'next' {
|
'n' | 'next' {
|
||||||
Parse(parser, tkNEXT, 0, command);
|
Parse(parser, tkNEXT, 0, command);
|
||||||
continue;
|
continue;
|
||||||
@ -328,5 +333,8 @@ bool ParseLine(const char *iter, Command *command)
|
|||||||
Parse(parser, 0, 0, command);
|
Parse(parser, 0, 0, command);
|
||||||
ParseFree(parser, free);
|
ParseFree(parser, free);
|
||||||
|
|
||||||
|
if (!command->valid)
|
||||||
|
fprintf(stderr,"I don't understand.\n");
|
||||||
|
|
||||||
return command->valid;
|
return command->valid;
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ uint32_t debuggerReadLong(uint32_t);
|
|||||||
}
|
}
|
||||||
|
|
||||||
%parse_failure {
|
%parse_failure {
|
||||||
fprintf(stderr,"I don't understand.\n");
|
//fprintf(stderr,"I don't understand.\n");
|
||||||
command->valid = false;
|
command->valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +59,12 @@ stmt ::= expr(a) EOL.
|
|||||||
command->argv[0] = a;
|
command->argv[0] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stmt ::= STAR EOL.
|
||||||
|
{
|
||||||
|
command->action = PrintRegisters;
|
||||||
|
command->argc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
stmt ::= PRINT expr(a) EOL.
|
stmt ::= PRINT expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = Print;
|
command->action = Print;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user