diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-12-18 15:43:29 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-12-18 15:43:29 +0000 |
commit | eb3074a4fe3b7c86d2a3ca139eb881964f2f23e1 (patch) | |
tree | 5ce1e76df21acb8d0b5b209fe7f2461a78c36a8e /misc/pascal/insn16/prun/pdbg.c | |
parent | af6cfa901fa8cc78607976e8ed8aedc195500aff (diff) | |
download | nuttx-eb3074a4fe3b7c86d2a3ca139eb881964f2f23e1.tar.gz nuttx-eb3074a4fe3b7c86d2a3ca139eb881964f2f23e1.tar.bz2 nuttx-eb3074a4fe3b7c86d2a3ca139eb881964f2f23e1.zip |
Update to use stdint/stdbool.h
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2383 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'misc/pascal/insn16/prun/pdbg.c')
-rw-r--r-- | misc/pascal/insn16/prun/pdbg.c | 1494 |
1 files changed, 748 insertions, 746 deletions
diff --git a/misc/pascal/insn16/prun/pdbg.c b/misc/pascal/insn16/prun/pdbg.c index c617359c7..9b7c4f5d2 100644 --- a/misc/pascal/insn16/prun/pdbg.c +++ b/misc/pascal/insn16/prun/pdbg.c @@ -1,746 +1,748 @@ -/**********************************************************************
- * pdbg.c
- * P-Code Debugger
- *
- * Copyright (C) 2008 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- **********************************************************************/
-
-/**********************************************************************
- * Included Files
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-
-#include "keywords.h"
-#include "pdefs.h"
-#include "podefs.h"
-#include "pinsn16.h"
-#include "pxdefs.h"
-#include "pedefs.h"
-
-#include "paslib.h"
-#include "pinsn.h"
-#include "pexec.h"
-#include "pdbg.h"
-
-/**********************************************************************
- * Definitions
- **********************************************************************/
-
-#define TRACE_ARRAY_SIZE 16
-#define MAX_BREAK_POINTS 8
-#define DISPLAY_STACK_SIZE 16
-#define DISPLAY_INST_SIZE 16
-
-/**********************************************************************
- * Private Type Definitions
- **********************************************************************/
-
-enum command_e
-{
- eCMD_NONE = 0,
- eCMD_RESET,
- eCMD_RUN,
- eCMD_STEP,
- eCMD_NEXT,
- eCMD_GO,
- eCMD_BS,
- eCMD_BC,
- eCMD_DP,
- eCMD_DT,
- eCMD_DS,
- eCMD_DI,
- eCMD_DB,
- eCMD_HELP,
- eCMD_QUIT
-};
-
-struct trace_s
-{
- addr_t pc;
- addr_t sp;
- ustack_t tos;
-};
-typedef struct trace_s trace_t;
-
-/**********************************************************************
- * Private Constant Data
- **********************************************************************/
-
-/**********************************************************************
- * Private Data
- **********************************************************************/
-
-static enum command_e g_lastcmd = eCMD_NONE;
-static uint32 g_lastvalue;
-
-/**********************************************************************
- * Private Function Prototypes
- **********************************************************************/
-
-static void pdbg_showcommands(void);
-static void pdbg_execcommand(struct pexec_s *st, enum command_e cmd, uint32 value);
-static sint32 pdbg_readdecimal(char *ptr);
-static sint32 pdbg_readhex(char *ptr, sint32 defaultvalue);
-static void pdbg_programstatus(struct pexec_s *st);
-static addr_t pdbg_printpcode(struct pexec_s *st, addr_t pc, sint16 nitems);
-static addr_t pdbg_printstack(struct pexec_s *st, addr_t sp, sint16 nitems);
-static void pdbg_printregisters(struct pexec_s *st);
-static void pdbg_printtracearray(struct pexec_s *st);
-static void pdbg_addbreakpoint(addr_t pc);
-static void pdbg_deletebreakpoint(sint16 bpno);
-static void pdbg_printbreakpoints(struct pexec_s *st);
-static void pdbg_checkbreakpoint(struct pexec_s *st);
-static void pdbg_initdebugger(void);
-static void pdbg_debugpcode(struct pexec_s *st);
-
-/**********************************************************************
- * Global Variables
- **********************************************************************/
-
-/**********************************************************************
- * Private Variables
- **********************************************************************/
-
-/* Debugging variables */
-
-static trace_t g_tracearray[TRACE_ARRAY_SIZE];
- /* Holds execution histor */
-static uint16 g_tracendx;
- /* This is the index into the circular g_tracearray */
-static uint16 g_ntracepoints;
- /* This is the number of valid enties in g_tracearray */
-static addr_t g_breakpoint[MAX_BREAK_POINTS];
- /* Contains address associated with all active */
- /* break points. */
-static addr_t g_untilpoint;
- /* The 'g_untilpoint' is a temporary breakpoint */
-static uint16 g_nbreakpoints;
- /* Number of items in breakPoints[] */
-static addr_t g_displayloc;
- /* P-code display location display */
-static boolean g_bstopexecution;
- /* TRUE means to stop program execution */
-
-/* I/O variables */
-
-static char g_inline[LINE_SIZE+1];
- /* Command line buffer */
-
-/**********************************************************************
- * Public Functions
- **********************************************************************/
-
-void dbg_run(struct pexec_s *st)
-{
- addr_t pc;
- int i;
-
- pdbg_showcommands();
- pdbg_initdebugger();
- pdbg_programstatus(st);
-
- while (TRUE)
- {
- printf("CMD: ");
- (void) fgets(g_inline, LINE_SIZE, stdin);
- switch (toupper(g_inline[0]))
- {
- case 'R' :
- switch (toupper(g_inline[1])) {
- case 'E' : /* Reset */
- pdbg_execcommand(st, eCMD_RESET, 0);
- break;
- case 'U' : /* Run */
- pdbg_execcommand(st, eCMD_RUN, 0);
- break;
- default :
- printf("Unrecognized Command\n");
- pdbg_execcommand(st, eCMD_HELP, 0);
- break;
- } /* end switch */
- break;
- case 'S' : /* Single Step (into) */
- pdbg_execcommand(st, eCMD_STEP, 0);
- break;
- case 'N' : /* Single Step (over) */
- pdbg_execcommand(st, eCMD_NEXT, 0);
- break;
- case 'G' : /* Go */
- pdbg_execcommand(st, eCMD_GO, 0);
- break;
- case 'B' :
- switch (toupper(g_inline[1])) {
- case 'S' : /* Set Breakpoint */
- pc = pdbg_readhex(&g_inline[2], st->pc);
- pdbg_execcommand(st, eCMD_BS, pc);
- break;
- case 'C' : /* Clear Breakpoint */
- i = pdbg_readdecimal(&g_inline[2]);
- pdbg_execcommand(st, eCMD_BC, i);
- break;
- default :
- printf("Unrecognized Command\n");
- pdbg_execcommand(st, eCMD_HELP, 0);
- break;
- } /* end switch */
- break;
- case 'D' :
- switch (toupper(g_inline[1])) {
- case 'P' : /* Display Program Status */
- pdbg_execcommand(st, eCMD_DP, 0);
- break;
- case 'T' : /* Display Program Trace */
- pdbg_execcommand(st, eCMD_DT, 0);
- break;
- case 'S' : /* Display Stack */
- pc = pdbg_readhex(&g_inline[2], st->sp);
- pdbg_execcommand(st, eCMD_DS, pc);
- break;
- case 'I' : /* Display Instructions */
- pc = pdbg_readhex(&g_inline[2], st->pc);
- pdbg_execcommand(st, eCMD_DI, pc);
- break;
- case 'B' : /* Display Breakpoints */
- pdbg_execcommand(st, eCMD_DB, pc);
- break;
- default :
- printf("Unrecognized Command\n");
- pdbg_execcommand(st, eCMD_HELP, 0);
- break;
- } /* end switch */
- break;
- case 'Q' : /* Quit */
- pdbg_execcommand(st, eCMD_QUIT, pc);
- break;
- case 'H' : /* Help */
- case '?' :
- pdbg_execcommand(st, eCMD_HELP, 0);
- break;
- case '\0' : /* Repeat last command */
- case '\n' : /* Repeat last command */
- pdbg_execcommand(st, g_lastcmd, g_lastvalue);
- break;
- default :
- printf("Unrecognized Command\n");
- pdbg_execcommand(st, eCMD_HELP, 0);
- break;
- } /* end switch */
- } /* end while */
-
-} /* end pdbg_debugpcodeProgram */
-
-/**********************************************************************
- * Private Functions
- **********************************************************************/
-/* Show command characters */
-
-static void pdbg_showcommands(void)
-{
- printf("Commands:\n");
- printf(" RE[set] - Reset\n");
- printf(" RU[n] - Run\n");
- printf(" S[tep] - Single Step (Into)\n");
- printf(" N[ext] - Single Step (Over)\n");
- printf(" G[o] - Go\n");
- printf(" BS xxxx - Set Breakpoint\n");
- printf(" BC n - Clear Breakpoint\n");
- printf(" DP - Display Program Status\n");
- printf(" DT - Display Program Trace\n");
- printf(" DS [xxxx] - Display Stack\n");
- printf(" DI [xxxx] - Display Instructions\n");
- printf(" DB - Display Breakpoints\n");
- printf(" H or ? - Shows this list\n");
- printf(" Q[uit] - Quit\n");
-
-} /* end pdbg_showcommands */
-
-/***********************************************************************/
-static void pdbg_execcommand(struct pexec_s *st, enum command_e cmd, uint32 value)
-{
- /* Save the command to resuse if the user enters nothing */
-
- g_lastcmd = cmd;
- g_lastvalue = value;
-
- switch (cmd)
- {
- case eCMD_NONE: /* Do nothing */
- break;
- case eCMD_RESET: /* Reset */
- pexec_reset(st);
- pdbg_initdebugger();
- pdbg_programstatus(st);
- g_lastcmd = eCMD_NONE;
- break;
- case eCMD_RUN: /* Run */
- pexec_reset(st);
- pdbg_initdebugger();
- pdbg_debugpcode(st);
- pdbg_programstatus(st);
- break;
- case eCMD_STEP: /* Single Step (into)*/
- g_bstopexecution = TRUE;
- pdbg_debugpcode(st);
- pdbg_programstatus(st);
- break;
- case eCMD_NEXT: /* Single Step (over) */
- if (st->ispace[st->pc] == oPCAL)
- {
- g_bstopexecution = FALSE;
- g_untilpoint = st->pc + 4;
- }
- else
- {
- g_bstopexecution = TRUE;
- }
- pdbg_debugpcode(st);
- g_untilpoint = 0;
- pdbg_programstatus(st);
- break;
- case eCMD_GO: /* Go */
- g_bstopexecution = FALSE;
- pdbg_debugpcode(st);
- pdbg_programstatus(st);
- break;
- case eCMD_BS: /* Set Breakpoint */
- if (g_nbreakpoints >= MAX_BREAK_POINTS)
- {
- printf("Too many breakpoints\n");
- g_lastcmd = eCMD_NONE;
- }
- else if (value >= st->maxpc)
- {
- printf("Invalid address for breakpoint\n");
- g_lastcmd = eCMD_NONE;
- }
- else
- {
- pdbg_addbreakpoint(value);
- pdbg_printbreakpoints(st);
- } /* end else */
- break;
- case eCMD_BC: /* Clear Breakpoint */
- if ((value >= 1) && (value <= g_nbreakpoints))
- {
- pdbg_deletebreakpoint(value);
- }
- else
- {
- printf("Invalid breakpoint number\n");
- g_lastcmd = eCMD_NONE;
- }
- pdbg_printbreakpoints(st);
- break;
- case eCMD_DP: /* Display Program Status */
- pdbg_programstatus(st);
- break;
- case eCMD_DT: /* Display Program Trace */
- pdbg_printtracearray(st);
- break;
- case eCMD_DS: /* Display Stack */
- if (value > st->sp)
- {
- printf("Invalid stack address\n");
- g_lastcmd = eCMD_NONE;
- }
- else
- {
- g_lastvalue = pdbg_printstack(st, value, DISPLAY_STACK_SIZE);
- } /* end else */
- break;
- case eCMD_DI: /* Display Instructions */
- if (value >= st->maxpc)
- {
- printf("Invalid instruction address\n");
- g_lastcmd = eCMD_NONE;
- }
- else
- {
- g_lastvalue = pdbg_printpcode(st, value, DISPLAY_INST_SIZE);
- } /* end else */
- break;
- case eCMD_DB: /* Display Breakpoints */
- pdbg_printbreakpoints(st);
- break;
- case eCMD_QUIT: /* Quit */
- printf("Goodbye\n");
- exit(0);
- break;
- case eCMD_HELP: /* Help */
- default: /* Internal error */
- pdbg_showcommands();
- g_lastcmd = eCMD_NONE;
- break;
- } /* end switch */
-
-} /* end pdbg_execcommand */
-
-/***********************************************************************/
-/* Read a decimal value from the input string */
-
-static sint32 pdbg_readdecimal(char *ptr)
-{
- sint32 decimal = 0;
-
- while (!isspace(*ptr)) ptr++;
- while (isspace(*ptr)) ptr++;
- for (; ((*ptr >= '0') && (*ptr <= '9')); ptr++)
- decimal = 10*decimal + (sint32)*ptr - (sint32)'0';
-
- return decimal;
-
-} /* end pdbg_readdecimal */
-/***********************************************************************/
-/* Read a hexadecimal value from the input string */
-
-static sint32 pdbg_readhex(char *ptr, sint32 defaultvalue)
-{
- char c;
- sint32 hex = 0;
- boolean found = FALSE;
-
- while (!isspace(*ptr)) ptr++;
- while (isspace(*ptr)) ptr++;
- while (TRUE) {
-
- c = toupper(*ptr);
- if ((c >= '0') && (c <= '9')) {
- hex = ((hex << 4) | ((sint32)c - (sint32)'0'));
- found = TRUE;
- } /* end if */
- else if ((c >= 'A') && (c <= 'F')) {
- hex = ((hex << 4) | ((sint32)c - (sint32)'A' + 10));
- found = TRUE;
- } /* end else if */
- else {
- if (found)
- return hex;
- else
- return defaultvalue;
- } /* end else */
- ptr++;
-
- } /* end while */
-
-} /* end pdbg_readhex */
-
-/***********************************************************************/
-/* Print the disassembled P-Code at PC */
-
-static void pdbg_programstatus(struct pexec_s *st)
-{
- (void)pdbg_printpcode(st, st->pc, 1);
- (void)pdbg_printstack(st, st->sp, 2);
- pdbg_printregisters(st);
-
-} /* end pdbg_programstatus */
-
-/***********************************************************************/
-/* Print the disassembled P-Code at PC */
-
-static addr_t pdbg_printpcode(struct pexec_s *st, addr_t pc, sint16 nitems)
-{
- OPTYPE op;
- addr_t opsize;
- ubyte *address;
-
- for (; ((pc < st->maxpc) && (nitems > 0)); nitems--)
- {
- address = &st->ispace[pc];
-
- op.op = *address++;
- op.arg1 = 0;
- op.arg2 = 0;
- opsize = 1;
- printf("PC:%04x %02x", pc, op.op);
-
- if ((op.op & o8) != 0)
- {
- op.arg1 = *address++;
- printf("%02x", op.arg1);
- opsize++;
- } /* end if */
- else
- printf("..");
-
- if ((op.op & o16) != 0)
- {
- op.arg2 = ((*address++) << 8);
- op.arg2 |= *address++;
- printf("%04x", op.arg2);
- opsize += 2;
- } /* end if */
- else
- printf("....");
-
- /* The disassemble it to stdout */
-
- printf(" ");
- insn_DisassemblePCode(stdout, &op);
-
- /* Get the address of the next P-Code */
-
- pc += opsize;
-
- } /* end for */
-
- return pc;
-
-} /* end pdbg_printpcode */
-
-/***********************************************************************/
-/* Print the stack value at SP */
-
-static addr_t pdbg_printstack(struct pexec_s *st, addr_t sp, sint16 nitems)
-{
- sint32 isp;
-
- if ((st->sp < st->stacksize) && (sp <= st->sp))
- {
- isp = BTOISTACK(sp);
- printf("SP:%04x %04x\n", sp, st->dstack.i[isp]);
-
- for (isp--, sp -= BPERI, nitems--;
- ((isp >= 0) && (nitems > 0));
- isp--, sp -= BPERI, nitems--)
- printf(" %04x %04x\n", sp, st->dstack.i[isp] & 0xffff);
- } /* end if */
- else
- {
- printf("SP:%04x BAD\n", sp);
- } /* end else */
-
- return sp;
-} /* end pdbg_printstack */
-
-/***********************************************************************/
-/* Print the base register */
-
-static void pdbg_printregisters(struct pexec_s *st)
-{
- if (st->fp <= st->sp)
- printf("FP:%04x ", st->fp);
-
- printf("CSP:%04x\n", st->csp);
-
-} /* end pdbg_printregisters */
-
-/***********************************************************************/
-/* Print the g_tracearray */
-
-static void pdbg_printtracearray(struct pexec_s *st)
-{
- int nprinted;
- int index;
-
- index = g_tracendx + TRACE_ARRAY_SIZE - g_ntracepoints;
- if (index >= TRACE_ARRAY_SIZE)
- index -= TRACE_ARRAY_SIZE;
-
- for (nprinted = 0; nprinted < g_ntracepoints; nprinted++) {
-
- printf("SP:%04x %04x ",
- g_tracearray[ index ].sp, g_tracearray[ index ].tos);
-
- /* Print the instruction executed at this traced address */
- (void)pdbg_printpcode(st, g_tracearray[ index ].pc, 1);
-
- /* Index to the next trace entry */
- if (++index >= TRACE_ARRAY_SIZE)
- index = 0;
-
- } /* end for */
-
-} /* end pdbg_printtracearray */
-
-/***********************************************************************/
-/* Add a breakpoint to the breakpoint array */
-
-static void pdbg_addbreakpoint(addr_t pc)
-{
- int i;
-
- /* Is there room for another breakpoint? */
-
- if (g_nbreakpoints < MAX_BREAK_POINTS)
- {
- /* Yes..Check if the breakpoint already exists */
-
- for (i = 0; i < g_nbreakpoints; i++)
- {
- if (g_breakpoint[i] == pc)
- {
- /* It is already set. Return without doing anything */
-
- return;
- }
- }
-
- /* The breakpoint is not already set -- set it */
-
- g_breakpoint[g_nbreakpoints++] = pc;
- } /* end if */
-
-} /* end pdbg_addbreakpoint */
-
-/***********************************************************************/
-/* Remove a breakpoint from the breakpoint array */
-
-static void pdbg_deletebreakpoint(sint16 bpno)
-{
- if ((bpno >= 1) && (bpno <= g_nbreakpoints)) {
-
- for (; (bpno < g_nbreakpoints); bpno++)
- g_breakpoint[bpno-1] = g_breakpoint[bpno];
-
- g_nbreakpoints--;
-
- } /* end if */
-
-} /* end pdbg_deletebreakpoint */
-
-/***********************************************************************/
-/* Print the breakpoint array */
-
-static void pdbg_printbreakpoints(struct pexec_s *st)
-{
- int i;
-
- printf("BP:# Address P-Code\n");
- for (i = 0; i < g_nbreakpoints; i++)
- {
- printf("BP:%d ", (i+1));
- (void)pdbg_printpcode(st, g_breakpoint[i], 1);
- } /* end for */
-
-} /* end pdbg_printbreakpoints */
-
-/***********************************************************************/
-/* Check if a breakpoint is set at the current value of program counter.
- * If so, print the instruction and stop execution. */
-
-static void pdbg_checkbreakpoint(struct pexec_s *st)
-{
- uint16 bpIndex;
-
- /* Check for a user breakpoint */
-
- for (bpIndex = 0;
- ((bpIndex < g_nbreakpoints) && (!g_bstopexecution));
- bpIndex++)
- {
- if (g_breakpoint[bpIndex] == st->pc)
- {
- printf("Breakpoint #%d -- Execution Stopped\n", (bpIndex+1));
- g_bstopexecution = TRUE;
- return;
- } /* end if */
- } /* end for */
-
-} /* end pdbg_checkbreakpoint */
-
-/***********************************************************************/
-/* Initialize Debugger variables */
-
-static void pdbg_initdebugger(void)
-{
- g_bstopexecution = FALSE;
- g_displayloc = 0;
- g_tracendx = 0;
- g_ntracepoints = 0;
-}
-
-/***********************************************************************/
-/* This function executes the P-Code program until a stopping condition
- * is encountered. */
-
-static void pdbg_debugpcode(struct pexec_s *st)
-{
- uint16 errno;
-
- do {
- /* Trace the next instruction execution */
-
- g_tracearray[g_tracendx].pc = st->pc;
- g_tracearray[g_tracendx].sp = st->sp;
- if (st->sp < st->stacksize)
- g_tracearray[g_tracendx].tos = st->dstack.i[BTOISTACK(st->sp)];
- else
- g_tracearray[g_tracendx].tos = 0;
-
- if (++g_tracendx >= TRACE_ARRAY_SIZE)
- g_tracendx = 0;
- if (g_ntracepoints < TRACE_ARRAY_SIZE)
- g_ntracepoints++;
-
- /* Execute the instruction */
-
- errno = pexec(st);
-
- /* Check for exceptional stopping conditions */
-
- if (errno != eNOERROR)
- {
- if (errno == eEXIT)
- printf("Normal Termination\n");
- else
- printf("Runtime error 0x%02x -- Execution Stopped\n", errno);
- g_bstopexecution = TRUE;
- } /* end if */
-
- /* Check for normal stopping conditions */
-
- if (!g_bstopexecution)
- {
- /* Check for attempt to execute code outside of legal range */
-
- if (st->pc >= st->maxpc)
- g_bstopexecution = TRUE;
-
- /* Check for a temporary breakpoint */
-
- else if ((g_untilpoint > 0) && (g_untilpoint == st->pc))
- g_bstopexecution = TRUE;
-
- /* Check if there is a breakpoint at the next instruction */
-
- else if (g_nbreakpoints > 0)
- pdbg_checkbreakpoint(st);
- }
-
- } while (!g_bstopexecution);
-
-} /* end pdbg_debugpcode */
+/********************************************************************** + * pdbg.c + * P-Code Debugger + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **********************************************************************/ + +/********************************************************************** + * Included Files + **********************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <ctype.h> + +#include "keywords.h" +#include "pdefs.h" +#include "podefs.h" +#include "pinsn16.h" +#include "pxdefs.h" +#include "pedefs.h" + +#include "paslib.h" +#include "pinsn.h" +#include "pexec.h" +#include "pdbg.h" + +/********************************************************************** + * Pre-processor Definitions + **********************************************************************/ + +#define TRACE_ARRAY_SIZE 16 +#define MAX_BREAK_POINTS 8 +#define DISPLAY_STACK_SIZE 16 +#define DISPLAY_INST_SIZE 16 + +/********************************************************************** + * Private Type Definitions + **********************************************************************/ + +enum command_e +{ + eCMD_NONE = 0, + eCMD_RESET, + eCMD_RUN, + eCMD_STEP, + eCMD_NEXT, + eCMD_GO, + eCMD_BS, + eCMD_BC, + eCMD_DP, + eCMD_DT, + eCMD_DS, + eCMD_DI, + eCMD_DB, + eCMD_HELP, + eCMD_QUIT +}; + +struct trace_s +{ + addr_t pc; + addr_t sp; + ustack_t tos; +}; +typedef struct trace_s trace_t; + +/********************************************************************** + * Private Constant Data + **********************************************************************/ + +/********************************************************************** + * Private Data + **********************************************************************/ + +static enum command_e g_lastcmd = eCMD_NONE; +static uint32_t g_lastvalue; + +/********************************************************************** + * Private Function Prototypes + **********************************************************************/ + +static void pdbg_showcommands(void); +static void pdbg_execcommand(struct pexec_s *st, enum command_e cmd, uint32_t value); +static int32_t pdbg_readdecimal(char *ptr); +static int32_t pdbg_readhex(char *ptr, int32_t defaultvalue); +static void pdbg_programstatus(struct pexec_s *st); +static addr_t pdbg_printpcode(struct pexec_s *st, addr_t pc, int16_t nitems); +static addr_t pdbg_printstack(struct pexec_s *st, addr_t sp, int16_t nitems); +static void pdbg_printregisters(struct pexec_s *st); +static void pdbg_printtracearray(struct pexec_s *st); +static void pdbg_addbreakpoint(addr_t pc); +static void pdbg_deletebreakpoint(int16_t bpno); +static void pdbg_printbreakpoints(struct pexec_s *st); +static void pdbg_checkbreakpoint(struct pexec_s *st); +static void pdbg_initdebugger(void); +static void pdbg_debugpcode(struct pexec_s *st); + +/********************************************************************** + * Global Variables + **********************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/* Debugging variables */ + +static trace_t g_tracearray[TRACE_ARRAY_SIZE]; + /* Holds execution histor */ +static uint16_t g_tracendx; + /* This is the index into the circular g_tracearray */ +static uint16_t g_ntracepoints; + /* This is the number of valid enties in g_tracearray */ +static addr_t g_breakpoint[MAX_BREAK_POINTS]; + /* Contains address associated with all active */ + /* break points. */ +static addr_t g_untilpoint; + /* The 'g_untilpoint' is a temporary breakpoint */ +static uint16_t g_nbreakpoints; + /* Number of items in breakPoints[] */ +static addr_t g_displayloc; + /* P-code display location display */ +static bool g_bstopexecution; + /* true means to stop program execution */ + +/* I/O variables */ + +static char g_inline[LINE_SIZE+1]; + /* Command line buffer */ + +/********************************************************************** + * Public Functions + **********************************************************************/ + +void dbg_run(struct pexec_s *st) +{ + addr_t pc; + int i; + + pdbg_showcommands(); + pdbg_initdebugger(); + pdbg_programstatus(st); + + while (true) + { + printf("CMD: "); + (void) fgets(g_inline, LINE_SIZE, stdin); + switch (toupper(g_inline[0])) + { + case 'R' : + switch (toupper(g_inline[1])) { + case 'E' : /* Reset */ + pdbg_execcommand(st, eCMD_RESET, 0); + break; + case 'U' : /* Run */ + pdbg_execcommand(st, eCMD_RUN, 0); + break; + default : + printf("Unrecognized Command\n"); + pdbg_execcommand(st, eCMD_HELP, 0); + break; + } /* end switch */ + break; + case 'S' : /* Single Step (into) */ + pdbg_execcommand(st, eCMD_STEP, 0); + break; + case 'N' : /* Single Step (over) */ + pdbg_execcommand(st, eCMD_NEXT, 0); + break; + case 'G' : /* Go */ + pdbg_execcommand(st, eCMD_GO, 0); + break; + case 'B' : + switch (toupper(g_inline[1])) { + case 'S' : /* Set Breakpoint */ + pc = pdbg_readhex(&g_inline[2], st->pc); + pdbg_execcommand(st, eCMD_BS, pc); + break; + case 'C' : /* Clear Breakpoint */ + i = pdbg_readdecimal(&g_inline[2]); + pdbg_execcommand(st, eCMD_BC, i); + break; + default : + printf("Unrecognized Command\n"); + pdbg_execcommand(st, eCMD_HELP, 0); + break; + } /* end switch */ + break; + case 'D' : + switch (toupper(g_inline[1])) { + case 'P' : /* Display Program Status */ + pdbg_execcommand(st, eCMD_DP, 0); + break; + case 'T' : /* Display Program Trace */ + pdbg_execcommand(st, eCMD_DT, 0); + break; + case 'S' : /* Display Stack */ + pc = pdbg_readhex(&g_inline[2], st->sp); + pdbg_execcommand(st, eCMD_DS, pc); + break; + case 'I' : /* Display Instructions */ + pc = pdbg_readhex(&g_inline[2], st->pc); + pdbg_execcommand(st, eCMD_DI, pc); + break; + case 'B' : /* Display Breakpoints */ + pdbg_execcommand(st, eCMD_DB, pc); + break; + default : + printf("Unrecognized Command\n"); + pdbg_execcommand(st, eCMD_HELP, 0); + break; + } /* end switch */ + break; + case 'Q' : /* Quit */ + pdbg_execcommand(st, eCMD_QUIT, pc); + break; + case 'H' : /* Help */ + case '?' : + pdbg_execcommand(st, eCMD_HELP, 0); + break; + case '\0' : /* Repeat last command */ + case '\n' : /* Repeat last command */ + pdbg_execcommand(st, g_lastcmd, g_lastvalue); + break; + default : + printf("Unrecognized Command\n"); + pdbg_execcommand(st, eCMD_HELP, 0); + break; + } /* end switch */ + } /* end while */ + +} /* end pdbg_debugpcodeProgram */ + +/********************************************************************** + * Private Functions + **********************************************************************/ +/* Show command characters */ + +static void pdbg_showcommands(void) +{ + printf("Commands:\n"); + printf(" RE[set] - Reset\n"); + printf(" RU[n] - Run\n"); + printf(" S[tep] - Single Step (Into)\n"); + printf(" N[ext] - Single Step (Over)\n"); + printf(" G[o] - Go\n"); + printf(" BS xxxx - Set Breakpoint\n"); + printf(" BC n - Clear Breakpoint\n"); + printf(" DP - Display Program Status\n"); + printf(" DT - Display Program Trace\n"); + printf(" DS [xxxx] - Display Stack\n"); + printf(" DI [xxxx] - Display Instructions\n"); + printf(" DB - Display Breakpoints\n"); + printf(" H or ? - Shows this list\n"); + printf(" Q[uit] - Quit\n"); + +} /* end pdbg_showcommands */ + +/***********************************************************************/ +static void pdbg_execcommand(struct pexec_s *st, enum command_e cmd, uint32_t value) +{ + /* Save the command to resuse if the user enters nothing */ + + g_lastcmd = cmd; + g_lastvalue = value; + + switch (cmd) + { + case eCMD_NONE: /* Do nothing */ + break; + case eCMD_RESET: /* Reset */ + pexec_reset(st); + pdbg_initdebugger(); + pdbg_programstatus(st); + g_lastcmd = eCMD_NONE; + break; + case eCMD_RUN: /* Run */ + pexec_reset(st); + pdbg_initdebugger(); + pdbg_debugpcode(st); + pdbg_programstatus(st); + break; + case eCMD_STEP: /* Single Step (into)*/ + g_bstopexecution = true; + pdbg_debugpcode(st); + pdbg_programstatus(st); + break; + case eCMD_NEXT: /* Single Step (over) */ + if (st->ispace[st->pc] == oPCAL) + { + g_bstopexecution = false; + g_untilpoint = st->pc + 4; + } + else + { + g_bstopexecution = true; + } + pdbg_debugpcode(st); + g_untilpoint = 0; + pdbg_programstatus(st); + break; + case eCMD_GO: /* Go */ + g_bstopexecution = false; + pdbg_debugpcode(st); + pdbg_programstatus(st); + break; + case eCMD_BS: /* Set Breakpoint */ + if (g_nbreakpoints >= MAX_BREAK_POINTS) + { + printf("Too many breakpoints\n"); + g_lastcmd = eCMD_NONE; + } + else if (value >= st->maxpc) + { + printf("Invalid address for breakpoint\n"); + g_lastcmd = eCMD_NONE; + } + else + { + pdbg_addbreakpoint(value); + pdbg_printbreakpoints(st); + } /* end else */ + break; + case eCMD_BC: /* Clear Breakpoint */ + if ((value >= 1) && (value <= g_nbreakpoints)) + { + pdbg_deletebreakpoint(value); + } + else + { + printf("Invalid breakpoint number\n"); + g_lastcmd = eCMD_NONE; + } + pdbg_printbreakpoints(st); + break; + case eCMD_DP: /* Display Program Status */ + pdbg_programstatus(st); + break; + case eCMD_DT: /* Display Program Trace */ + pdbg_printtracearray(st); + break; + case eCMD_DS: /* Display Stack */ + if (value > st->sp) + { + printf("Invalid stack address\n"); + g_lastcmd = eCMD_NONE; + } + else + { + g_lastvalue = pdbg_printstack(st, value, DISPLAY_STACK_SIZE); + } /* end else */ + break; + case eCMD_DI: /* Display Instructions */ + if (value >= st->maxpc) + { + printf("Invalid instruction address\n"); + g_lastcmd = eCMD_NONE; + } + else + { + g_lastvalue = pdbg_printpcode(st, value, DISPLAY_INST_SIZE); + } /* end else */ + break; + case eCMD_DB: /* Display Breakpoints */ + pdbg_printbreakpoints(st); + break; + case eCMD_QUIT: /* Quit */ + printf("Goodbye\n"); + exit(0); + break; + case eCMD_HELP: /* Help */ + default: /* Internal error */ + pdbg_showcommands(); + g_lastcmd = eCMD_NONE; + break; + } /* end switch */ + +} /* end pdbg_execcommand */ + +/***********************************************************************/ +/* Read a decimal value from the input string */ + +static int32_t pdbg_readdecimal(char *ptr) +{ + int32_t decimal = 0; + + while (!isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; + for (; ((*ptr >= '0') && (*ptr <= '9')); ptr++) + decimal = 10*decimal + (int32_t)*ptr - (int32_t)'0'; + + return decimal; + +} /* end pdbg_readdecimal */ +/***********************************************************************/ +/* Read a hexadecimal value from the input string */ + +static int32_t pdbg_readhex(char *ptr, int32_t defaultvalue) +{ + char c; + int32_t hex = 0; + bool found = false; + + while (!isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; + while (true) { + + c = toupper(*ptr); + if ((c >= '0') && (c <= '9')) { + hex = ((hex << 4) | ((int32_t)c - (int32_t)'0')); + found = true; + } /* end if */ + else if ((c >= 'A') && (c <= 'F')) { + hex = ((hex << 4) | ((int32_t)c - (int32_t)'A' + 10)); + found = true; + } /* end else if */ + else { + if (found) + return hex; + else + return defaultvalue; + } /* end else */ + ptr++; + + } /* end while */ + +} /* end pdbg_readhex */ + +/***********************************************************************/ +/* Print the disassembled P-Code at PC */ + +static void pdbg_programstatus(struct pexec_s *st) +{ + (void)pdbg_printpcode(st, st->pc, 1); + (void)pdbg_printstack(st, st->sp, 2); + pdbg_printregisters(st); + +} /* end pdbg_programstatus */ + +/***********************************************************************/ +/* Print the disassembled P-Code at PC */ + +static addr_t pdbg_printpcode(struct pexec_s *st, addr_t pc, int16_t nitems) +{ + OPTYPE op; + addr_t opsize; + uint8_t *address; + + for (; ((pc < st->maxpc) && (nitems > 0)); nitems--) + { + address = &st->ispace[pc]; + + op.op = *address++; + op.arg1 = 0; + op.arg2 = 0; + opsize = 1; + printf("PC:%04x %02x", pc, op.op); + + if ((op.op & o8) != 0) + { + op.arg1 = *address++; + printf("%02x", op.arg1); + opsize++; + } /* end if */ + else + printf(".."); + + if ((op.op & o16) != 0) + { + op.arg2 = ((*address++) << 8); + op.arg2 |= *address++; + printf("%04x", op.arg2); + opsize += 2; + } /* end if */ + else + printf("...."); + + /* The disassemble it to stdout */ + + printf(" "); + insn_DisassemblePCode(stdout, &op); + + /* Get the address of the next P-Code */ + + pc += opsize; + + } /* end for */ + + return pc; + +} /* end pdbg_printpcode */ + +/***********************************************************************/ +/* Print the stack value at SP */ + +static addr_t pdbg_printstack(struct pexec_s *st, addr_t sp, int16_t nitems) +{ + int32_t isp; + + if ((st->sp < st->stacksize) && (sp <= st->sp)) + { + isp = BTOISTACK(sp); + printf("SP:%04x %04x\n", sp, st->dstack.i[isp]); + + for (isp--, sp -= BPERI, nitems--; + ((isp >= 0) && (nitems > 0)); + isp--, sp -= BPERI, nitems--) + printf(" %04x %04x\n", sp, st->dstack.i[isp] & 0xffff); + } /* end if */ + else + { + printf("SP:%04x BAD\n", sp); + } /* end else */ + + return sp; +} /* end pdbg_printstack */ + +/***********************************************************************/ +/* Print the base register */ + +static void pdbg_printregisters(struct pexec_s *st) +{ + if (st->fp <= st->sp) + printf("FP:%04x ", st->fp); + + printf("CSP:%04x\n", st->csp); + +} /* end pdbg_printregisters */ + +/***********************************************************************/ +/* Print the g_tracearray */ + +static void pdbg_printtracearray(struct pexec_s *st) +{ + int nprinted; + int index; + + index = g_tracendx + TRACE_ARRAY_SIZE - g_ntracepoints; + if (index >= TRACE_ARRAY_SIZE) + index -= TRACE_ARRAY_SIZE; + + for (nprinted = 0; nprinted < g_ntracepoints; nprinted++) { + + printf("SP:%04x %04x ", + g_tracearray[ index ].sp, g_tracearray[ index ].tos); + + /* Print the instruction executed at this traced address */ + (void)pdbg_printpcode(st, g_tracearray[ index ].pc, 1); + + /* Index to the next trace entry */ + if (++index >= TRACE_ARRAY_SIZE) + index = 0; + + } /* end for */ + +} /* end pdbg_printtracearray */ + +/***********************************************************************/ +/* Add a breakpoint to the breakpoint array */ + +static void pdbg_addbreakpoint(addr_t pc) +{ + int i; + + /* Is there room for another breakpoint? */ + + if (g_nbreakpoints < MAX_BREAK_POINTS) + { + /* Yes..Check if the breakpoint already exists */ + + for (i = 0; i < g_nbreakpoints; i++) + { + if (g_breakpoint[i] == pc) + { + /* It is already set. Return without doing anything */ + + return; + } + } + + /* The breakpoint is not already set -- set it */ + + g_breakpoint[g_nbreakpoints++] = pc; + } /* end if */ + +} /* end pdbg_addbreakpoint */ + +/***********************************************************************/ +/* Remove a breakpoint from the breakpoint array */ + +static void pdbg_deletebreakpoint(int16_t bpno) +{ + if ((bpno >= 1) && (bpno <= g_nbreakpoints)) { + + for (; (bpno < g_nbreakpoints); bpno++) + g_breakpoint[bpno-1] = g_breakpoint[bpno]; + + g_nbreakpoints--; + + } /* end if */ + +} /* end pdbg_deletebreakpoint */ + +/***********************************************************************/ +/* Print the breakpoint array */ + +static void pdbg_printbreakpoints(struct pexec_s *st) +{ + int i; + + printf("BP:# Address P-Code\n"); + for (i = 0; i < g_nbreakpoints; i++) + { + printf("BP:%d ", (i+1)); + (void)pdbg_printpcode(st, g_breakpoint[i], 1); + } /* end for */ + +} /* end pdbg_printbreakpoints */ + +/***********************************************************************/ +/* Check if a breakpoint is set at the current value of program counter. + * If so, print the instruction and stop execution. */ + +static void pdbg_checkbreakpoint(struct pexec_s *st) +{ + uint16_t bpIndex; + + /* Check for a user breakpoint */ + + for (bpIndex = 0; + ((bpIndex < g_nbreakpoints) && (!g_bstopexecution)); + bpIndex++) + { + if (g_breakpoint[bpIndex] == st->pc) + { + printf("Breakpoint #%d -- Execution Stopped\n", (bpIndex+1)); + g_bstopexecution = true; + return; + } /* end if */ + } /* end for */ + +} /* end pdbg_checkbreakpoint */ + +/***********************************************************************/ +/* Initialize Debugger variables */ + +static void pdbg_initdebugger(void) +{ + g_bstopexecution = false; + g_displayloc = 0; + g_tracendx = 0; + g_ntracepoints = 0; +} + +/***********************************************************************/ +/* This function executes the P-Code program until a stopping condition + * is encountered. */ + +static void pdbg_debugpcode(struct pexec_s *st) +{ + uint16_t errno; + + do { + /* Trace the next instruction execution */ + + g_tracearray[g_tracendx].pc = st->pc; + g_tracearray[g_tracendx].sp = st->sp; + if (st->sp < st->stacksize) + g_tracearray[g_tracendx].tos = st->dstack.i[BTOISTACK(st->sp)]; + else + g_tracearray[g_tracendx].tos = 0; + + if (++g_tracendx >= TRACE_ARRAY_SIZE) + g_tracendx = 0; + if (g_ntracepoints < TRACE_ARRAY_SIZE) + g_ntracepoints++; + + /* Execute the instruction */ + + errno = pexec(st); + + /* Check for exceptional stopping conditions */ + + if (errno != eNOERROR) + { + if (errno == eEXIT) + printf("Normal Termination\n"); + else + printf("Runtime error 0x%02x -- Execution Stopped\n", errno); + g_bstopexecution = true; + } /* end if */ + + /* Check for normal stopping conditions */ + + if (!g_bstopexecution) + { + /* Check for attempt to execute code outside of legal range */ + + if (st->pc >= st->maxpc) + g_bstopexecution = true; + + /* Check for a temporary breakpoint */ + + else if ((g_untilpoint > 0) && (g_untilpoint == st->pc)) + g_bstopexecution = true; + + /* Check if there is a breakpoint at the next instruction */ + + else if (g_nbreakpoints > 0) + pdbg_checkbreakpoint(st); + } + + } while (!g_bstopexecution); + +} /* end pdbg_debugpcode */ |