Firmware: added next command (transient breakpoint)

Change-Id: Id4c04097b6021f369e9bea0d427b770d4294a125
This commit is contained in:
David Banks
2019-10-29 16:07:51 +00:00
parent c6bc245b3d
commit 3a5b0e46e2

View File

@@ -37,6 +37,7 @@
char *cmdStrings[] = { char *cmdStrings[] = {
"help", "help",
"continue", "continue",
"next",
"step", "step",
#if defined(CPU_EMBEDDED) #if defined(CPU_EMBEDDED)
"regs", "regs",
@@ -78,6 +79,7 @@ char *cmdStrings[] = {
void (*cmdFuncs[])(char *params) = { void (*cmdFuncs[])(char *params) = {
doCmdHelp, doCmdHelp,
doCmdContinue, doCmdContinue,
doCmdNext,
doCmdStep, doCmdStep,
#if defined(CPU_EMBEDDED) #if defined(CPU_EMBEDDED)
doCmdRegs, doCmdRegs,
@@ -390,6 +392,9 @@ char * triggerStrings[NUM_TRIGGERS] = {
// The current memory address (e.g. used when disassembling) // The current memory address (e.g. used when disassembling)
unsigned int memAddr = 0; unsigned int memAddr = 0;
// The address of the next instruction
unsigned int nextAddr = 0;
// When single stepping, trace (i.e. log) event N instructions // When single stepping, trace (i.e. log) event N instructions
// Setting this to 0 will disable logging // Setting this to 0 will disable logging
long trace; long trace;
@@ -697,7 +702,7 @@ void logAddr() {
logCycleCount(OFFSET_CNTL, OFFSET_CNTH); logCycleCount(OFFSET_CNTL, OFFSET_CNTH);
#if defined(CPU_EMBEDDED) #if defined(CPU_EMBEDDED)
//log0("%04X\n", i_addr); //log0("%04X\n", i_addr);
disMem(memAddr); nextAddr = disMem(memAddr);
#else #else
log0("%04X\n", memAddr); log0("%04X\n", memAddr);
#endif #endif
@@ -753,13 +758,32 @@ void setTrace(long i) {
} }
// Set the breakpoint state variables // Set the breakpoint state variables
void setBreakpoint(int i, unsigned int addr, unsigned int mask, unsigned int mode, int trigger) {
void logBreakpoint(unsigned int addr, unsigned int mode) {
logMode(mode); logMode(mode);
log0(" set at %04X\n", addr); log0(" set at %04X\n", addr);
breakpoints[i] = addr & mask; }
masks[i] = mask;
modes[i] = mode; void logTooManyBreakpoints() {
triggers[i] = trigger; log0("All %d breakpoints are already set\n", numbkpts);
}
void setBreakpoint(int n, unsigned int addr, unsigned int mask, unsigned int mode, int trigger) {
breakpoints[n] = addr & mask;
masks[n] = mask;
modes[n] = mode;
triggers[n] = trigger;
}
void clearBreakpoint(int n) {
int i;
for (i = n; i < numbkpts; i++) {
breakpoints[i] = breakpoints[i + 1];
masks[i] = masks[i + 1];
modes[i] = modes[i + 1];
triggers[i] = triggers[i + 1];
}
numbkpts--;
} }
// A generic helper that does most of the work of the watch/breakpoint commands // A generic helper that does most of the work of the watch/breakpoint commands
@@ -779,13 +803,14 @@ void genericBreakpoint(char *params, unsigned int mode) {
if (trigger == -1) { if (trigger == -1) {
trigger = triggers[i]; trigger = triggers[i];
} }
logBreakpoint(addr, mode);
setBreakpoint(i, addr, mask, modes[i] | mode, trigger); setBreakpoint(i, addr, mask, modes[i] | mode, trigger);
} }
return; return;
} }
} }
if (numbkpts == MAXBKPTS) { if (numbkpts == MAXBKPTS) {
log0("All %d breakpoints are already set\n", numbkpts); logTooManyBreakpoints();
return; return;
} }
numbkpts++; numbkpts++;
@@ -795,6 +820,7 @@ void genericBreakpoint(char *params, unsigned int mode) {
} }
for (i = numbkpts - 2; i >= -1; i--) { for (i = numbkpts - 2; i >= -1; i--) {
if (i == -1 || breakpoints[i] < addr) { if (i == -1 || breakpoints[i] < addr) {
logBreakpoint(addr, mode);
setBreakpoint(i + 1, addr, mask, mode, trigger); setBreakpoint(i + 1, addr, mask, mode, trigger);
return; return;
} else { } else {
@@ -1229,7 +1255,6 @@ void doCmdWatchWrIO(char *params) {
#endif #endif
void doCmdClear(char *params) { void doCmdClear(char *params) {
int i;
int n = lookupBreakpoint(params); int n = lookupBreakpoint(params);
if (n < 0) { if (n < 0) {
return; return;
@@ -1237,13 +1262,7 @@ void doCmdClear(char *params) {
log0("Removing "); log0("Removing ");
logMode(modes[n]); logMode(modes[n]);
log0(" at %04X\n", breakpoints[n]); log0(" at %04X\n", breakpoints[n]);
for (i = n; i < numbkpts; i++) { clearBreakpoint(n);
breakpoints[i] = breakpoints[i + 1];
masks[i] = masks[i + 1];
modes[i] = modes[i + 1];
triggers[i] = triggers[i + 1];
}
numbkpts--;
} }
void doCmdTrigger(char *params) { void doCmdTrigger(char *params) {
@@ -1264,6 +1283,24 @@ void doCmdTrigger(char *params) {
} }
} }
// Set transient breakpoint on the next instruction
//
// This allows you to single step over a subroutine call, or
// continue exeuting until a loop exits.
//
// Note: the implemention is quite simplistic, and the transient breakpoint
// will be removed when continue exits, regardless of whether the transient
// breakpoint was hit.
void doCmdNext(char *params) {
if (numbkpts == MAXBKPTS) {
logTooManyBreakpoints();
return;
}
setBreakpoint(numbkpts++, nextAddr, 0xffff, 1 << BRKPT_EXEC, TRIGGER_ALWAYS);
doCmdContinue(params);
clearBreakpoint(numbkpts - 1);
}
void doCmdContinue(char *params) { void doCmdContinue(char *params) {
int i; int i;
int status; int status;