mirror of
https://github.com/ksherlock/mpw.git
synced 2025-02-08 07:30:34 +00:00
more debugger functionality
This commit is contained in:
parent
552d95f9e0
commit
27cd692790
316
bin/debugger.cpp
316
bin/debugger.cpp
@ -188,46 +188,52 @@ namespace {
|
||||
std::printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ParseLine(const char *iter, Command *command);
|
||||
|
||||
extern "C" {
|
||||
|
||||
uint32_t debuggerReadLong(uint32_t address)
|
||||
uint32_t disasm(uint32_t pc, uint16_t *op = nullptr)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
|
||||
static char strings[4][256];
|
||||
|
||||
if (pc >= Flags.memorySize)
|
||||
{
|
||||
if (address < Flags.memorySize)
|
||||
tmp = (tmp << 8) + Flags.memory[address++];
|
||||
if (op) *op = 0;
|
||||
return pc;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
uint16_t opcode = debuggerReadWord(pc);
|
||||
if (op) *op = opcode;
|
||||
|
||||
uint16_t debuggerReadWord(uint32_t address)
|
||||
if ((opcode & 0xf000) == 0xa000)
|
||||
{
|
||||
uint16_t tmp = 0;
|
||||
for (unsigned i = 0; i < 2; ++i)
|
||||
|
||||
const char *name;
|
||||
|
||||
name = TrapName(opcode);
|
||||
|
||||
if (name)
|
||||
{
|
||||
if (address < Flags.memorySize)
|
||||
tmp = (tmp << 8) + Flags.memory[address++];
|
||||
printf("$%08X %-51s ; %04X\n", pc, name, opcode);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
uint8_t debuggerReadByte(uint32_t address)
|
||||
else
|
||||
{
|
||||
if (address < Flags.memorySize)
|
||||
return Flags.memory[address];
|
||||
printf("$%08X Tool #$%04X ; %04X\n",
|
||||
pc, opcode, opcode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
pc += 2;
|
||||
return pc;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DebugHelp(const Command &cmd)
|
||||
{
|
||||
printf("help\n");
|
||||
@ -278,6 +284,8 @@ void DebugDump(const Command &cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DebugList(const Command &cmd)
|
||||
{
|
||||
// TODO -- if no address, use previous address.
|
||||
@ -291,41 +299,10 @@ void DebugList(const Command &cmd)
|
||||
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]);
|
||||
pc = disasm(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -333,8 +310,30 @@ void DebugList(const Command &cmd)
|
||||
|
||||
void DebugPrintRegisters(const Command &cmd)
|
||||
{
|
||||
printf("PC: %08X CSR: %04x\n", cpuGetPC(), cpuGetSR());
|
||||
char srbits[20];
|
||||
|
||||
uint16_t sr = cpuGetSR();
|
||||
|
||||
srbits[0] = sr & (1 << 15) ? 'T' : ' ';
|
||||
srbits[1] = sr & (1 << 14) ? 'T' : ' ';
|
||||
srbits[2] = sr & (1 << 13) ? 'S' : ' ';
|
||||
srbits[3] = sr & (1 << 12) ? 'M' : ' ';
|
||||
srbits[4] = ' ';
|
||||
srbits[5] = sr & (1 << 10) ? 'I' : ' ';
|
||||
srbits[6] = sr & (1 << 9) ? 'I' : ' ';
|
||||
srbits[7] = sr & (1 << 8) ? 'I' : ' ';
|
||||
srbits[8] = ' ';
|
||||
srbits[9] = ' ';
|
||||
srbits[10] = ' ';
|
||||
srbits[11] = sr & (1 << 4) ? 'X' : ' ';
|
||||
srbits[12] = sr & (1 << 3) ? 'N' : ' ';
|
||||
srbits[13] = sr & (1 << 2) ? 'Z' : ' ';
|
||||
srbits[14] = sr & (1 << 1) ? 'V' : ' ';
|
||||
srbits[15] = sr & (1 << 0) ? 'C' : ' ';
|
||||
srbits[16] = 0;
|
||||
|
||||
|
||||
printf(" 0 1 2 3 4 5 6 7\n");
|
||||
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)
|
||||
@ -346,8 +345,178 @@ void DebugPrintRegisters(const Command &cmd)
|
||||
cpuGetAReg(4), cpuGetAReg(5), cpuGetAReg(6), cpuGetAReg(7)
|
||||
);
|
||||
|
||||
printf("PC: %08X CSR: %04x %s\n", cpuGetPC(), sr, srbits);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DebugToolBreak(Command &cmd)
|
||||
{
|
||||
for (unsigned i = 0; i < cmd.argc; ++i)
|
||||
{
|
||||
int32_t tool = (int32_t)cmd.argv[i];
|
||||
bool remove = false;
|
||||
|
||||
if (tool < 0)
|
||||
{
|
||||
tool = -tool;
|
||||
remove = true;
|
||||
}
|
||||
|
||||
if (tool >= 0xa000 && tool <= 0xafff)
|
||||
{
|
||||
if (remove) tbrkRemove(tool);
|
||||
else tbrkAdd(tool);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid tool: $%04x\n", tool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugBreak(Command &cmd)
|
||||
{
|
||||
// 24-bit only, - address to remove.
|
||||
for (unsigned i = 0; i < cmd.argc; ++i)
|
||||
{
|
||||
int32_t address = (int32_t)cmd.argv[i];
|
||||
bool remove = false;
|
||||
|
||||
if (address < 0)
|
||||
{
|
||||
address = -address;
|
||||
remove = true;
|
||||
}
|
||||
|
||||
if ((address & 0xff000000) == 0)
|
||||
{
|
||||
if (remove) brkRemove(address);
|
||||
else brkAdd(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid address: $%08x\n", address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DebugStep(const Command &cmd)
|
||||
{
|
||||
// TODO - step n to step specified # of instructions.
|
||||
// TODO -- step @address to step until address?
|
||||
|
||||
// disasm 1 line, execute it.
|
||||
|
||||
int count = 0;
|
||||
if (cmd.argc == 1) count = (int)cmd.argv[0];
|
||||
if (count < 1) count = 1;
|
||||
|
||||
// TODO -- move to common function...
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
uint16_t op;
|
||||
cpuExecuteInstruction();
|
||||
|
||||
if (cpuGetStop()) break; // will this also be set by an interrupt?
|
||||
|
||||
|
||||
uint32_t pc = cpuGetPC();
|
||||
disasm(pc, &op);
|
||||
|
||||
// check for pc breaks
|
||||
if (brkLookup(pc))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// check for toolbreaks.
|
||||
if ((op & 0xf000) == 0xa000)
|
||||
{
|
||||
if (tbrkLookup(op))
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t sp = cpuGetAReg(7);
|
||||
if (sp < Flags.stackRange.first)
|
||||
{
|
||||
fprintf(stderr, "Stack overflow error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (sp > Flags.stackRange.second)
|
||||
{
|
||||
fprintf(stderr, "Stack underflow error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugSetARegister(Command &cmd)
|
||||
{
|
||||
if (cmd.argc != 2) return;
|
||||
unsigned reg = cmd.argv[0];
|
||||
uint32_t value = cmd.argv[1];
|
||||
|
||||
if (reg > 7) return;
|
||||
if (reg == 7)
|
||||
{
|
||||
// sp/7 must be aligned.
|
||||
if (value & 0x01)
|
||||
{
|
||||
fprintf(stderr, "Address is not aligned: $%08x\n", value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (value > Flags.memorySize)
|
||||
{
|
||||
fprintf(stderr, "Warning: address exceeeds memory size: $%08x\n", value);
|
||||
}
|
||||
|
||||
cpuSetAReg(reg, value);
|
||||
}
|
||||
|
||||
|
||||
void DebugSetDRegister(Command &cmd)
|
||||
{
|
||||
if (cmd.argc != 2) return;
|
||||
unsigned reg = cmd.argv[0];
|
||||
uint32_t value = cmd.argv[1];
|
||||
|
||||
cpuSetDReg(reg, value);
|
||||
}
|
||||
|
||||
void DebugSetXRegister(Command &cmd)
|
||||
{
|
||||
if (cmd.argc != 2) return;
|
||||
unsigned reg = cmd.argv[0];
|
||||
uint32_t value = cmd.argv[1];
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
if (value & 0x01)
|
||||
{
|
||||
fprintf(stderr, "Address is not aligned: $%08x\n", value);
|
||||
return;
|
||||
}
|
||||
if (value > Flags.memorySize)
|
||||
{
|
||||
fprintf(stderr, "Warning: address exceeeds memory size: $%08x\n", value);
|
||||
}
|
||||
cpuSetPC(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reg == 1)
|
||||
{
|
||||
cpuSetSR(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// todo -- add sigint trap. it shall set a flag to break.
|
||||
|
||||
void DebugShell()
|
||||
@ -355,6 +524,11 @@ void DebugShell()
|
||||
char *cp;
|
||||
|
||||
add_history("!Andy, it still has history!");
|
||||
|
||||
// start it up
|
||||
printf("MPW Debugger shell\n\n");
|
||||
disasm(cpuGetPC());
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cp = readline("] ");
|
||||
@ -391,6 +565,30 @@ void DebugShell()
|
||||
DebugPrintRegisters(cmd);
|
||||
break;
|
||||
|
||||
case Step:
|
||||
DebugStep(cmd);
|
||||
break;
|
||||
|
||||
case TBreak:
|
||||
DebugToolBreak(cmd);
|
||||
break;
|
||||
|
||||
case Break:
|
||||
DebugBreak(cmd);
|
||||
break;
|
||||
|
||||
case SetARegister:
|
||||
DebugSetARegister(cmd);
|
||||
break;
|
||||
|
||||
case SetDRegister:
|
||||
DebugSetDRegister(cmd);
|
||||
break;
|
||||
|
||||
case SetXRegister:
|
||||
DebugSetXRegister(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugHelp(cmd);
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user