699 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			699 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
/* -*-C-*-
 | 
						|
*******************************************************************************
 | 
						|
*
 | 
						|
* File:         pa_stub.c
 | 
						|
* RCS:          $Header$
 | 
						|
* Description:  main routines for PA RISC monitor stub
 | 
						|
* Author:       Robert Quist
 | 
						|
* Created:      Mon Nov  1 10:00:36 1993
 | 
						|
* Modified:     Fri Nov 12 15:14:23 1993 (Robert Quist) quist@hpfcrdq
 | 
						|
* Language:     C
 | 
						|
* Package:      N/A
 | 
						|
* Status:       Experimental (Do Not Distribute)
 | 
						|
*
 | 
						|
*******************************************************************************
 | 
						|
*/
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 | 
						|
		THIS SOFTWARE IS NOT COPYRIGHTED
 | 
						|
 | 
						|
   HP offers the following for use in the public domain.  HP makes no
 | 
						|
   warranty with regard to the software or it's performance and the
 | 
						|
   user accepts the software "AS IS" with all faults.
 | 
						|
 | 
						|
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
 | 
						|
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | 
						|
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 *
 | 
						|
 *  Description:     low level support for gdb debugger. $
 | 
						|
 *
 | 
						|
 *  Considerations:  only works on target hardware $
 | 
						|
 *
 | 
						|
 *  NOTES:           See Below $
 | 
						|
 *
 | 
						|
 *    To enable debugger support, two things need to happen.
 | 
						|
 *
 | 
						|
 *  One, a call to set_debug_traps() is necessary in order to allow
 | 
						|
 *  any breakpoints or error conditions to be properly intercepted and
 | 
						|
 *  reported to gdb.  
 | 
						|
 *
 | 
						|
 *  Two, a breakpoint needs to be generated to begin communication.
 | 
						|
 *  This is most easily accomplished by a call to breakpoint().
 | 
						|
 *  breakpoint() simulates a breakpoint
 | 
						|
 | 
						|
 | 
						|
 *************
 | 
						|
 *
 | 
						|
 *    The following gdb commands are supported:
 | 
						|
 *
 | 
						|
 * command          function                               Return value
 | 
						|
 *
 | 
						|
 *    g             return the value of the CPU registers  hex data or ENN
 | 
						|
 *    G             set the value of the CPU registers     OK or ENN
 | 
						|
 *
 | 
						|
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
 | 
						|
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
 | 
						|
 *
 | 
						|
 *    c             Resume at current address              SNN   ( signal NN)
 | 
						|
 *    cAA..AA       Continue at address AA..AA             SNN
 | 
						|
 *
 | 
						|
 *    s             Step one instruction                   SNN
 | 
						|
 *    sAA..AA       Step one instruction from AA..AA       SNN
 | 
						|
 *
 | 
						|
 *    k             kill
 | 
						|
 *
 | 
						|
 *    ?             What was the last sigval ?             SNN   (signal NN)
 | 
						|
 *
 | 
						|
 *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
 | 
						|
 *							   baud rate
 | 
						|
 *
 | 
						|
 | 
						|
 ************
 | 
						|
 * All commands and responses are sent with a packet which includes a
 | 
						|
 * checksum.  A packet consists of :
 | 
						|
 *
 | 
						|
 * $<packet info>#<checksum>.
 | 
						|
 *
 | 
						|
 * where
 | 
						|
 * <packet info> :: <characters representing the command or response>
 | 
						|
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
 | 
						|
 *
 | 
						|
 * When a packet is received, it is first acknowledged with either '+' or '-'.
 | 
						|
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
 | 
						|
 *
 | 
						|
 * Example:
 | 
						|
 *
 | 
						|
 * Host:                  Reply:
 | 
						|
 * $m0,10#2a               +$00010203040506070809101112131415#42
 | 
						|
 *
 | 
						|
 ****************************************************************************/
 | 
						|
#include <signal.h>
 | 
						|
#include "hppa-defs.h"
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
 *
 | 
						|
 * external low-level support
 | 
						|
 */
 | 
						|
#define	OPT_PDC_CACHE	     5
 | 
						|
#define	OPT_PDC_ADD_VALID   12
 | 
						|
#define PGZ_MEM_PDC	0x0388	/* location of PDC_ENTRY in memory    */
 | 
						|
#define CALL_PDC	(*(int (*)())((int *)(*((int *)PGZ_MEM_PDC))))
 | 
						|
 | 
						|
extern putDebugChar();   /* write a single character      */
 | 
						|
extern getDebugChar();   /* read and return a single char */
 | 
						|
extern FICE();           /* flush i cache entry */
 | 
						|
extern INLINE_BREAK();   /* break for user call */
 | 
						|
 | 
						|
#define RADDR_ALIGN(s,r) (s = ((unsigned int *) ((((int) r ) + 7 ) & 0xFFFFFFF8)))
 | 
						|
 | 
						|
/************************************************************************/
 | 
						|
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
 | 
						|
/* at least NUMREGBYTES*2 are needed for register packets */
 | 
						|
 | 
						|
#define BUFMAX 2048
 | 
						|
 | 
						|
#define NUMGPRS	  32
 | 
						|
#define NUMSRS	   8
 | 
						|
#define	NUMCRS	  32
 | 
						|
#define	NUMSPCLS   3
 | 
						|
#define	NUMFPRS	  32
 | 
						|
 | 
						|
#define NUMGPRBYTES	4
 | 
						|
#define NUMSRBYTES	4
 | 
						|
#define	NUMCRBYTES	4
 | 
						|
#define	NUMSPCLBYTES	4
 | 
						|
#define NUMFPRBYTES	8
 | 
						|
 | 
						|
/* Number of bytes of registers.  */
 | 
						|
#define	NUMREGBYTES \
 | 
						|
	(  (NUMGPRS * NUMGPRBYTES) \
 | 
						|
         + (NUMSRS * NUMSRBYTES)   \
 | 
						|
         + (NUMCRS * NUMCRBYTES)   \
 | 
						|
	 + (NUMSPCLS * NUMSPCLBYTES) \
 | 
						|
	 + (NUMFPRS * NUMFPRBYTES) \
 | 
						|
        )
 | 
						|
         
 | 
						|
 | 
						|
enum regnames   {GR0,  GR1,  GR2,  GR3,  GR4,  GR5,  GR6,  GR7,
 | 
						|
		 GR8,  GR9,  GR10, GR11, GR12, GR13, GR14, GR15,
 | 
						|
		 GR16, GR17, GR18, GR19, GR20, GR21, GR22, GR23,
 | 
						|
		 GR24, GR25, GR26, GR27, GR28, GR29, GR30, GR31,
 | 
						|
                 
 | 
						|
                 SR0,  SR1,  SR2,  SR3,  SR4,  SR5,  SR6,  SR7,
 | 
						|
 | 
						|
                 CR0,  CR1,  CR2,  CR3,  CR4,  CR5,  CR6,  CR7,
 | 
						|
		 CR8,  CR9,  CR10, CR11, CR12, CR13, CR14, CR15,
 | 
						|
		 CR16, CR17H,CR18H,CR19, CR20, CR21, CR22, CR23,
 | 
						|
		 CR24, CR25, CR26, CR27, CR28, CR29, CR30, CR31,
 | 
						|
                 
 | 
						|
                 CR17T,CR18T,CPUD0 };
 | 
						|
 | 
						|
enum fregnames  {FPR0,  FPR1,  FPR2,  FPR3,  FPR4,  FPR5,  FPR6,  FPR7,
 | 
						|
		 FPR8,  FPR9,  FPR10, FPR11, FPR12, FPR13, FPR14, FPR15,
 | 
						|
		 FPR16, FPR17, FPR18, FPR19, FPR20, FPR21, FPR22, FPR23,
 | 
						|
		 FPR24, FPR25, FPR26, FPR27, FPR28, FPR29, FPR30, FPR31 };
 | 
						|
 | 
						|
#define PC  CR18H
 | 
						|
#define NPC CR18T
 | 
						|
#define SP  GR30
 | 
						|
                
 | 
						|
struct registers {
 | 
						|
       int intregs[NUMGPRS + NUMSRS + NUMCRS + NUMSPCLS];
 | 
						|
       int fpregs [NUMFPRS * 2];
 | 
						|
                 };    
 | 
						|
/* Global Variables */
 | 
						|
 | 
						|
static int initialized = 0;	/* !0 means we've been initialized */
 | 
						|
static unsigned char hexchars[]="0123456789abcdef";
 | 
						|
static unsigned char remcomInBuffer[BUFMAX];
 | 
						|
static unsigned char remcomOutBuffer[BUFMAX];
 | 
						|
static unsigned int  i_cache_params[6];
 | 
						|
 | 
						|
/* This table contains the mapping between PA hardware exception
 | 
						|
   types, and signals, which are primarily what GDB understands.  It also
 | 
						|
   indicates which hardware traps we need to commandeer when initializing
 | 
						|
   the stub.
 | 
						|
 | 
						|
   The only two currently used are Recovery counter (single stepping)
 | 
						|
   and Break trap ( break points ).
 | 
						|
*/
 | 
						|
 | 
						|
static struct hard_trap_info
 | 
						|
{
 | 
						|
  unsigned char tt;		/* Trap number for PA-RISC */
 | 
						|
  unsigned char signo;		/* Signal that we map this trap into */
 | 
						|
} hard_trap_info[] = {
 | 
						|
/* 1  High priority machine check */
 | 
						|
/* 2  Power failure interrupt*/
 | 
						|
/* 3  Recovery counter -- init */
 | 
						|
/* 4  External interrupt */
 | 
						|
/* 5  Low priority machine check */
 | 
						|
  {6, SIGSEGV},			/* Instruction TLB miss/page fault */
 | 
						|
  {7, SIGSEGV},			/* Memory protection */
 | 
						|
  {8, SIGILL},			/* Illegal instruction */
 | 
						|
  {9, SIGTRAP},			/* Break instruction -- init */
 | 
						|
  {10,SIGILL},			/* Privileged instruction */
 | 
						|
  {11,SIGILL},			/* Privileged register */
 | 
						|
  {12,SIGUSR1},			/* Overflow */
 | 
						|
  {13,SIGUSR2},			/* Conditional */
 | 
						|
  {14,SIGEMT},			/* Assist Exception */
 | 
						|
  {15,SIGSEGV},			/* Data TLB miss/page fault */
 | 
						|
  {16,SIGSEGV},			/* Non-access Instruction TLB miss */
 | 
						|
  {17,SIGSEGV},			/* Non-access Data TLB miss/page fault */
 | 
						|
  {18,SIGSEGV},			/* Data memory protection/ unaligned data reference */
 | 
						|
  {19,SIGTRAP},			/* Data memory break */
 | 
						|
  {20,SIGSEGV},			/* TLB dirty bit */
 | 
						|
  {21,SIGSEGV},			/* Page reference */
 | 
						|
  {22,SIGEMT},			/* Assist emulation */
 | 
						|
  {23,SIGILL},			/* Higher-privilege */
 | 
						|
  {24,SIGILL},			/* Lower-privilege */
 | 
						|
  {25,SIGTRAP},			/* Taken branch */
 | 
						|
  {0, 0}			/* Must be last */
 | 
						|
};
 | 
						|
 | 
						|
/* Functions */
 | 
						|
/*========================================================================== */
 | 
						|
 | 
						|
/* Convert ch from a hex digit to an int */
 | 
						|
 | 
						|
static int
 | 
						|
hex(ch)
 | 
						|
     unsigned char ch;
 | 
						|
{
 | 
						|
  if (ch >= 'a' && ch <= 'f')
 | 
						|
    return ch-'a'+10;
 | 
						|
  if (ch >= '0' && ch <= '9')
 | 
						|
    return ch-'0';
 | 
						|
  if (ch >= 'A' && ch <= 'F')
 | 
						|
    return ch-'A'+10;
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
/* scan for the sequence $<data>#<checksum>     */
 | 
						|
 | 
						|
static void
 | 
						|
getpacket(buffer)
 | 
						|
     char *buffer;
 | 
						|
{
 | 
						|
  unsigned char checksum;
 | 
						|
  unsigned char xmitcsum;
 | 
						|
  int i;
 | 
						|
  int count;
 | 
						|
  unsigned char ch;
 | 
						|
 | 
						|
  do
 | 
						|
    {
 | 
						|
      /* wait around for the start character, ignore all other characters */
 | 
						|
      strobe();
 | 
						|
      while ((ch = getDebugChar()) != '$') ;
 | 
						|
 | 
						|
      checksum = 0;
 | 
						|
      xmitcsum = -1;
 | 
						|
 | 
						|
      count = 0;
 | 
						|
 | 
						|
      /* now, read until a # or end of buffer is found */
 | 
						|
      while (count < BUFMAX)
 | 
						|
	{
 | 
						|
	  ch = getDebugChar();
 | 
						|
	  if (ch == '#')
 | 
						|
	    break;
 | 
						|
	  checksum = checksum + ch;
 | 
						|
	  buffer[count] = ch;
 | 
						|
	  count = count + 1;
 | 
						|
	}
 | 
						|
 | 
						|
      if (count >= BUFMAX)
 | 
						|
	continue;
 | 
						|
 | 
						|
      buffer[count] = 0;
 | 
						|
 | 
						|
      if (ch == '#')
 | 
						|
	{
 | 
						|
	  xmitcsum = hex(getDebugChar()) << 4;
 | 
						|
	  xmitcsum |= hex(getDebugChar());
 | 
						|
 | 
						|
#if TESTING
 | 
						|
	  /* Humans shouldn't have to figure out checksums to type to it. */
 | 
						|
	  putDebugChar ('+');
 | 
						|
	  return;
 | 
						|
#endif
 | 
						|
	  if (checksum != xmitcsum)
 | 
						|
	    putDebugChar('-');	/* failed checksum */
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      putDebugChar('+'); /* successful transfer */
 | 
						|
	      /* if a sequence char is present, reply the sequence ID */
 | 
						|
	      if (buffer[2] == ':')
 | 
						|
		{
 | 
						|
		  putDebugChar(buffer[0]);
 | 
						|
		  putDebugChar(buffer[1]);
 | 
						|
		  /* remove sequence chars from buffer */
 | 
						|
		  count = strlen(buffer);
 | 
						|
		  for (i=3; i <= count; i++)
 | 
						|
		    buffer[i-3] = buffer[i];
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
  while (checksum != xmitcsum);
 | 
						|
}
 | 
						|
 | 
						|
/* send the packet in buffer.  */
 | 
						|
 | 
						|
static void
 | 
						|
putpacket(buffer)
 | 
						|
     unsigned char *buffer;
 | 
						|
{
 | 
						|
  unsigned char checksum;
 | 
						|
  int count;
 | 
						|
  unsigned char ch;
 | 
						|
 | 
						|
  /*  $<packet info>#<checksum>. */
 | 
						|
 | 
						|
  do
 | 
						|
    {
 | 
						|
      putDebugChar('$');
 | 
						|
      checksum = 0;
 | 
						|
      count = 0;
 | 
						|
 | 
						|
      while (ch = buffer[count])
 | 
						|
	{
 | 
						|
	  if (! putDebugChar(ch))
 | 
						|
	    return;
 | 
						|
	  checksum += ch;
 | 
						|
	  count += 1;
 | 
						|
	}
 | 
						|
 | 
						|
      putDebugChar('#');
 | 
						|
      putDebugChar(hexchars[checksum >> 4]);
 | 
						|
      putDebugChar(hexchars[checksum & 0xf]);
 | 
						|
      } while (getDebugChar() != '+');
 | 
						|
}
 | 
						|
 | 
						|
/* Convert the memory pointed to by mem into hex, placing result in buf.
 | 
						|
 * Return a pointer to the last char put in buf (null), in case of mem fault,
 | 
						|
 * return 0.
 | 
						|
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
 | 
						|
 * a 0, else treat a fault like any other fault in the stub.
 | 
						|
 */
 | 
						|
 | 
						|
static unsigned char *
 | 
						|
mem2hex(mem, buf, count, may_fault)
 | 
						|
     unsigned char *mem;
 | 
						|
     unsigned char *buf;
 | 
						|
     int count;
 | 
						|
     int may_fault;
 | 
						|
{
 | 
						|
  unsigned char ch;
 | 
						|
  int           check_addr,
 | 
						|
                new_addr;
 | 
						|
 | 
						|
  check_addr = 0;
 | 
						|
 | 
						|
  while (count-- > 0)
 | 
						|
    {
 | 
						|
      if (may_fault)
 | 
						|
      { new_addr = ((int) (mem+3)) & 0xFFFFFFF8;
 | 
						|
        if (new_addr != check_addr)
 | 
						|
        { check_addr = new_addr;
 | 
						|
          if (pdc_call(OPT_PDC_ADD_VALID,0,check_addr)) return 0;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      ch = *mem++;
 | 
						|
      *buf++ = hexchars[ch >> 4];
 | 
						|
      *buf++ = hexchars[ch & 0xf];
 | 
						|
    }
 | 
						|
 | 
						|
  *buf = 0;
 | 
						|
 | 
						|
  return buf;
 | 
						|
}
 | 
						|
 | 
						|
/* convert the hex array pointed to by buf into binary to be placed in mem
 | 
						|
 * return a pointer to the character AFTER the last byte written */
 | 
						|
 | 
						|
static unsigned char *
 | 
						|
hex2mem(buf, mem, count, may_fault)
 | 
						|
     unsigned char *buf;
 | 
						|
     unsigned char *mem;
 | 
						|
     int count;
 | 
						|
     int may_fault;
 | 
						|
{
 | 
						|
  int          i;
 | 
						|
  unsigned int ch;
 | 
						|
  int          check_addr,
 | 
						|
               new_addr;
 | 
						|
 | 
						|
  check_addr = 0;
 | 
						|
 | 
						|
  for (i=0; i<count; i++)
 | 
						|
    {
 | 
						|
      ch = hex(*buf++) << 4;
 | 
						|
      ch |= hex(*buf++);
 | 
						|
      if (may_fault)
 | 
						|
      { new_addr = ((int)(mem+3)) & 0xFFFFFFF8;
 | 
						|
        if (new_addr != check_addr)
 | 
						|
        { check_addr = new_addr;
 | 
						|
          if (pdc_call(OPT_PDC_ADD_VALID,0,check_addr)) return 0;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      *mem++ = ch;
 | 
						|
    }
 | 
						|
 | 
						|
  return mem;
 | 
						|
}
 | 
						|
 | 
						|
/* Set up exception handlers for traceing and breakpoints */
 | 
						|
 | 
						|
void
 | 
						|
set_debug_traps()
 | 
						|
{ 
 | 
						|
  unsigned int	R_addr[33];
 | 
						|
  unsigned int	*Raddr_ptr;
 | 
						|
  
 | 
						|
  setup_vectors();
 | 
						|
 
 | 
						|
  /* get cache params for use by flush_i_cache */
 | 
						|
  RADDR_ALIGN(Raddr_ptr,R_addr);
 | 
						|
 | 
						|
  if (pdc_call(OPT_PDC_CACHE,0,Raddr_ptr,0))
 | 
						|
    i_cache_params[0] = -1;
 | 
						|
  else
 | 
						|
    i_cache_params[0] = R_addr[0];
 | 
						|
 | 
						|
  i_cache_params[1] = Raddr_ptr[1];
 | 
						|
  i_cache_params[2] = Raddr_ptr[2];
 | 
						|
  i_cache_params[3] = Raddr_ptr[3];
 | 
						|
  i_cache_params[4] = Raddr_ptr[4];
 | 
						|
  i_cache_params[5] = Raddr_ptr[5];
 | 
						|
 | 
						|
  /* In case GDB is started before us, ack any packets (presumably
 | 
						|
     "$?#xx") sitting there.  */
 | 
						|
 | 
						|
  putDebugChar ('+');
 | 
						|
 | 
						|
  initialized = 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Convert the PA-RISC hardware trap number to a unix signal number. */
 | 
						|
 | 
						|
static int
 | 
						|
computeSignal(tt)
 | 
						|
     int tt;
 | 
						|
{
 | 
						|
  struct hard_trap_info *ht;
 | 
						|
 | 
						|
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
 | 
						|
    if (ht->tt == tt)
 | 
						|
      return ht->signo;
 | 
						|
 | 
						|
  return SIGHUP;		/* default for things we don't know about */
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * While we find nice hex chars, build an int.
 | 
						|
 * Return number of chars processed.
 | 
						|
 */
 | 
						|
 | 
						|
static int
 | 
						|
hexToInt(ptr, intValue)
 | 
						|
     unsigned char **ptr;
 | 
						|
     int *intValue;
 | 
						|
{
 | 
						|
  int numChars = 0;
 | 
						|
  int hexValue;
 | 
						|
 | 
						|
  *intValue = 0;
 | 
						|
 | 
						|
  while (**ptr)
 | 
						|
    {
 | 
						|
      hexValue = hex(**ptr);
 | 
						|
      if (hexValue < 0)
 | 
						|
	break;
 | 
						|
 | 
						|
      *intValue = (*intValue << 4) | hexValue;
 | 
						|
      numChars ++;
 | 
						|
 | 
						|
      (*ptr)++;
 | 
						|
    }
 | 
						|
 | 
						|
  return (numChars);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
flush_i_cache()
 | 
						|
 | 
						|
{
 | 
						|
  unsigned int addr,count,loop;
 | 
						|
 | 
						|
  if (i_cache_params[0] <= 0) return;
 | 
						|
 | 
						|
  addr = i_cache_params[2];
 | 
						|
  for (count = 0; count < i_cache_params[4]; count++)
 | 
						|
    { for ( loop = 0; loop < i_cache_params[5]; loop++) FICE(addr);
 | 
						|
      addr = addr + i_cache_params[3];
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * This function does all command procesing for interfacing to gdb.
 | 
						|
   return of 0 will execute DEBUG_GO (continue)
 | 
						|
   return of 1 will execute DEBUG_SS (single step)
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
handle_exception (registers,tt)
 | 
						|
  unsigned long *registers;
 | 
						|
  int  tt;			/* Trap type */
 | 
						|
{
 | 
						|
  int sigval;
 | 
						|
  int addr;
 | 
						|
  int length;
 | 
						|
  unsigned char *ptr;
 | 
						|
 | 
						|
  /* reply to host that an exception has occurred */
 | 
						|
  sigval = computeSignal(tt);
 | 
						|
  ptr = remcomOutBuffer;
 | 
						|
 | 
						|
  *ptr++ = 'T';
 | 
						|
  *ptr++ = hexchars[sigval >> 4];
 | 
						|
  *ptr++ = hexchars[sigval & 0xf];
 | 
						|
 | 
						|
/* could be lots of stuff here like PC and SP registers */
 | 
						|
 | 
						|
  *ptr++ = 0;
 | 
						|
 | 
						|
  putpacket(remcomOutBuffer);
 | 
						|
 | 
						|
  while (1)
 | 
						|
    {
 | 
						|
      remcomOutBuffer[0] = 0;
 | 
						|
 | 
						|
      getpacket(remcomInBuffer);
 | 
						|
      switch (remcomInBuffer[0])
 | 
						|
	{
 | 
						|
	case '?':
 | 
						|
	  remcomOutBuffer[0] = 'S';
 | 
						|
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
 | 
						|
	  remcomOutBuffer[2] = hexchars[sigval & 0xf];
 | 
						|
	  remcomOutBuffer[3] = 0;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'd':
 | 
						|
	  /* toggle debug flag */
 | 
						|
	  led_putnum (16);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'g':		/* return the value of the CPU registers */
 | 
						|
	  {
 | 
						|
	    ptr = remcomOutBuffer;
 | 
						|
            /* GR0..GR31 SR0..SR7 CR0..CR31 specials */
 | 
						|
	    ptr = mem2hex((char *)registers, ptr, NUMREGBYTES, 0);
 | 
						|
            /* need to add floating point registers */
 | 
						|
	  }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'G':	   /* set the value of the CPU registers - return OK */
 | 
						|
	  {
 | 
						|
	    ptr = &remcomInBuffer[1];
 | 
						|
            /* GR0..GR31 SR0..SR7 CR0..CR31 specials */
 | 
						|
	    hex2mem(ptr, (char *)registers, NUMREGBYTES, 0);
 | 
						|
	    strcpy(remcomOutBuffer,"OK 1");
 | 
						|
	  }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
 | 
						|
	  /* Try to read %x,%x.  */
 | 
						|
 | 
						|
	  ptr = &remcomInBuffer[1];
 | 
						|
 | 
						|
	  if (hexToInt(&ptr, &addr)
 | 
						|
	      && *ptr++ == ','
 | 
						|
	      && hexToInt(&ptr, &length))
 | 
						|
	    {
 | 
						|
	      if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
 | 
						|
		break;
 | 
						|
 | 
						|
	      strcpy (remcomOutBuffer, "E03");
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    strcpy(remcomOutBuffer,"E01");
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
 | 
						|
	  /* Try to read '%x,%x:'.  */
 | 
						|
 | 
						|
	  ptr = &remcomInBuffer[1];
 | 
						|
 | 
						|
	  if (hexToInt(&ptr, &addr)
 | 
						|
	      && *ptr++ == ','
 | 
						|
	      && hexToInt(&ptr, &length)
 | 
						|
	      && *ptr++ == ':')
 | 
						|
	    {
 | 
						|
	      if (hex2mem(ptr, (char *)addr, length, 1))
 | 
						|
		strcpy(remcomOutBuffer, "OK");
 | 
						|
	      else
 | 
						|
		strcpy(remcomOutBuffer, "E03");
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    strcpy(remcomOutBuffer, "E02");
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
 | 
						|
	  /* try to read optional parameter, pc unchanged if no parm */
 | 
						|
 | 
						|
	  ptr = &remcomInBuffer[1];
 | 
						|
	  if (hexToInt(&ptr, &addr))
 | 
						|
	    {
 | 
						|
	      registers[PC] = addr;
 | 
						|
	      registers[NPC] = addr + 4;
 | 
						|
	    }
 | 
						|
 | 
						|
/* Need to flush the instruction cache here, as we may have deposited a
 | 
						|
   breakpoint, and the icache probably has no way of knowing that a data ref to
 | 
						|
   some location may have changed something that is in the instruction cache.
 | 
						|
 */
 | 
						|
 | 
						|
	  flush_i_cache();
 | 
						|
	  return 0;		/* execute GO */
 | 
						|
 | 
						|
	  /* kill the program */
 | 
						|
	case 'k' :		/* do nothing */
 | 
						|
	  break;
 | 
						|
 | 
						|
        case 's' :              /* single step */
 | 
						|
	  /* try to read optional parameter, pc unchanged if no parm */
 | 
						|
 | 
						|
	  ptr = &remcomInBuffer[1];
 | 
						|
	  if (hexToInt(&ptr, &addr))
 | 
						|
	    {
 | 
						|
	      registers[PC] = addr;
 | 
						|
	      registers[NPC] = addr + 4;
 | 
						|
	    }
 | 
						|
/* Need to flush the instruction cache here, as we may have deposited a
 | 
						|
   breakpoint, and the icache probably has no way of knowing that a data ref to
 | 
						|
   some location may have changed something that is in the instruction cache.
 | 
						|
 */
 | 
						|
	  flush_i_cache();
 | 
						|
	  return 1;		/* execute Single Step */
 | 
						|
          break;
 | 
						|
 | 
						|
#if TESTING1
 | 
						|
	case 't':		/* Test feature */
 | 
						|
	  break;
 | 
						|
#endif
 | 
						|
	case 'r':		/* Reset */
 | 
						|
	  break;
 | 
						|
 | 
						|
#if TESTING2
 | 
						|
Disabled until we can unscrew this properly
 | 
						|
 | 
						|
	case 'b':	  /* bBB...  Set baud rate to BB... */
 | 
						|
	  {
 | 
						|
	    int baudrate;
 | 
						|
	    extern void set_timer_3();
 | 
						|
 | 
						|
	    ptr = &remcomInBuffer[1];
 | 
						|
	    if (!hexToInt(&ptr, &baudrate))
 | 
						|
	      {
 | 
						|
		strcpy(remcomOutBuffer,"B01");
 | 
						|
		break;
 | 
						|
	      }
 | 
						|
 | 
						|
	    /* Convert baud rate to uart clock divider */
 | 
						|
	    switch (baudrate)
 | 
						|
	      {
 | 
						|
	      case 38400:
 | 
						|
		baudrate = 16;
 | 
						|
		break;
 | 
						|
	      case 19200:
 | 
						|
		baudrate = 33;
 | 
						|
		break;
 | 
						|
	      case 9600:
 | 
						|
		baudrate = 65;
 | 
						|
		break;
 | 
						|
	      default:
 | 
						|
		strcpy(remcomOutBuffer,"B02");
 | 
						|
		goto x1;
 | 
						|
	      }
 | 
						|
 | 
						|
	    putpacket("OK 2");	/* Ack before changing speed */
 | 
						|
	    set_timer_3(baudrate); /* Set it */
 | 
						|
	  }
 | 
						|
x1:	  break;
 | 
						|
#endif
 | 
						|
	}			/* switch */
 | 
						|
 | 
						|
      /* reply to the request */
 | 
						|
      putpacket(remcomOutBuffer);
 | 
						|
    }
 | 
						|
  print ("\r\nEscaped handle_exception\r\n");
 | 
						|
}
 |