OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [m32r-stub.c] - Diff between revs 105 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 105 Rev 1765
/****************************************************************************
/****************************************************************************
 
 
                THIS SOFTWARE IS NOT COPYRIGHTED
                THIS SOFTWARE IS NOT COPYRIGHTED
 
 
   HP offers the following for use in the public domain.  HP makes no
   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
   warranty with regard to the software or it's performance and the
   user accepts the software "AS IS" with all faults.
   user accepts the software "AS IS" with all faults.
 
 
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
 
****************************************************************************/
****************************************************************************/
 
 
/****************************************************************************
/****************************************************************************
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
 *
 *
 *  Module name: remcom.c $
 *  Module name: remcom.c $
 *  Revision: 1.34 $
 *  Revision: 1.34 $
 *  Date: 91/03/09 12:29:49 $
 *  Date: 91/03/09 12:29:49 $
 *  Contributor:     Lake Stevens Instrument Division$
 *  Contributor:     Lake Stevens Instrument Division$
 *
 *
 *  Description:     low level support for gdb debugger. $
 *  Description:     low level support for gdb debugger. $
 *
 *
 *  Considerations:  only works on target hardware $
 *  Considerations:  only works on target hardware $
 *
 *
 *  Written by:      Glenn Engel $
 *  Written by:      Glenn Engel $
 *  ModuleState:     Experimental $
 *  ModuleState:     Experimental $
 *
 *
 *  NOTES:           See Below $
 *  NOTES:           See Below $
 *
 *
 *  Modified for M32R by Michael Snyder, Cygnus Support.
 *  Modified for M32R by Michael Snyder, Cygnus Support.
 *
 *
 *  To enable debugger support, two things need to happen.  One, a
 *  To enable debugger support, two things need to happen.  One, a
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
 *  or error conditions to be properly intercepted and reported to gdb.
 *  or error conditions to be properly intercepted and reported to gdb.
 *  Two, a breakpoint needs to be generated to begin communication.  This
 *  Two, a breakpoint needs to be generated to begin communication.  This
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
 *  simulates a breakpoint by executing a trap #1.
 *  simulates a breakpoint by executing a trap #1.
 *
 *
 *  The external function exceptionHandler() is
 *  The external function exceptionHandler() is
 *  used to attach a specific handler to a specific M32R vector number.
 *  used to attach a specific handler to a specific M32R vector number.
 *  It should use the same privilege level it runs at.  It should
 *  It should use the same privilege level it runs at.  It should
 *  install it as an interrupt gate so that interrupts are masked
 *  install it as an interrupt gate so that interrupts are masked
 *  while the handler runs.
 *  while the handler runs.
 *
 *
 *  Because gdb will sometimes write to the stack area to execute function
 *  Because gdb will sometimes write to the stack area to execute function
 *  calls, this program cannot rely on using the supervisor stack so it
 *  calls, this program cannot rely on using the supervisor stack so it
 *  uses it's own stack area reserved in the int array remcomStack.
 *  uses it's own stack area reserved in the int array remcomStack.
 *
 *
 *************
 *************
 *
 *
 *    The following gdb commands are supported:
 *    The following gdb commands are supported:
 *
 *
 * command          function                               Return value
 * command          function                               Return value
 *
 *
 *    g             return the value of the CPU registers  hex data or ENN
 *    g             return the value of the CPU registers  hex data or ENN
 *    G             set the value of the CPU registers     OK 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  Read LLLL bytes at address AA..AA      hex data or ENN
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
 *    XAA..AA,LLLL: Write LLLL binary bytes at address     OK or ENN
 *    XAA..AA,LLLL: Write LLLL binary bytes at address     OK or ENN
 *                  AA..AA
 *                  AA..AA
 *
 *
 *    c             Resume at current address              SNN   ( signal NN)
 *    c             Resume at current address              SNN   ( signal NN)
 *    cAA..AA       Continue at address AA..AA             SNN
 *    cAA..AA       Continue at address AA..AA             SNN
 *
 *
 *    s             Step one instruction                   SNN
 *    s             Step one instruction                   SNN
 *    sAA..AA       Step one instruction from AA..AA       SNN
 *    sAA..AA       Step one instruction from AA..AA       SNN
 *
 *
 *    k             kill
 *    k             kill
 *
 *
 *    ?             What was the last sigval ?             SNN   (signal NN)
 *    ?             What was the last sigval ?             SNN   (signal NN)
 *
 *
 * All commands and responses are sent with a packet which includes a
 * All commands and responses are sent with a packet which includes a
 * checksum.  A packet consists of
 * checksum.  A packet consists of
 *
 *
 * $<packet info>#<checksum>.
 * $<packet info>#<checksum>.
 *
 *
 * where
 * where
 * <packet info> :: <characters representing the command or response>
 * <packet info> :: <characters representing the command or response>
 * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
 * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
 *
 *
 * When a packet is received, it is first acknowledged with either '+' or '-'.
 * When a packet is received, it is first acknowledged with either '+' or '-'.
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
 *
 *
 * Example:
 * Example:
 *
 *
 * Host:                  Reply:
 * Host:                  Reply:
 * $m0,10#2a               +$00010203040506070809101112131415#42
 * $m0,10#2a               +$00010203040506070809101112131415#42
 *
 *
 ****************************************************************************/
 ****************************************************************************/
 
 
 
 
/************************************************************************
/************************************************************************
 *
 *
 * external low-level support routines
 * external low-level support routines
 */
 */
extern void putDebugChar();     /* write a single character      */
extern void putDebugChar();     /* write a single character      */
extern int getDebugChar();      /* read and return a single char */
extern int getDebugChar();      /* read and return a single char */
extern void exceptionHandler(); /* assign an exception handler   */
extern void exceptionHandler(); /* assign an exception handler   */
 
 
/*****************************************************************************
/*****************************************************************************
 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
 * at least NUMREGBYTES*2 are needed for register packets
 * at least NUMREGBYTES*2 are needed for register packets
 */
 */
#define BUFMAX 400
#define BUFMAX 400
 
 
static char initialized;  /* boolean flag. != 0 means we've been initialized */
static char initialized;  /* boolean flag. != 0 means we've been initialized */
 
 
int     remote_debug;
int     remote_debug;
/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
 
 
static const unsigned char hexchars[]="0123456789abcdef";
static const unsigned char hexchars[]="0123456789abcdef";
 
 
#define NUMREGS 24
#define NUMREGS 24
 
 
/* Number of bytes of registers.  */
/* Number of bytes of registers.  */
#define NUMREGBYTES (NUMREGS * 4)
#define NUMREGBYTES (NUMREGS * 4)
enum regnames { R0,  R1,  R2,  R3,  R4,  R5,  R6,   R7,
enum regnames { R0,  R1,  R2,  R3,  R4,  R5,  R6,   R7,
                R8,  R9,  R10, R11, R12, R13, R14,  R15,
                R8,  R9,  R10, R11, R12, R13, R14,  R15,
                PSW, CBR, SPI, SPU, BPC, PC,  ACCL, ACCH };
                PSW, CBR, SPI, SPU, BPC, PC,  ACCL, ACCH };
 
 
enum SYS_calls {
enum SYS_calls {
        SYS_null,
        SYS_null,
        SYS_exit,
        SYS_exit,
        SYS_open,
        SYS_open,
        SYS_close,
        SYS_close,
        SYS_read,
        SYS_read,
        SYS_write,
        SYS_write,
        SYS_lseek,
        SYS_lseek,
        SYS_unlink,
        SYS_unlink,
        SYS_getpid,
        SYS_getpid,
        SYS_kill,
        SYS_kill,
        SYS_fstat,
        SYS_fstat,
        SYS_sbrk,
        SYS_sbrk,
        SYS_fork,
        SYS_fork,
        SYS_execve,
        SYS_execve,
        SYS_wait4,
        SYS_wait4,
        SYS_link,
        SYS_link,
        SYS_chdir,
        SYS_chdir,
        SYS_stat,
        SYS_stat,
        SYS_utime,
        SYS_utime,
        SYS_chown,
        SYS_chown,
        SYS_chmod,
        SYS_chmod,
        SYS_time,
        SYS_time,
        SYS_pipe };
        SYS_pipe };
 
 
static int registers[NUMREGS];
static int registers[NUMREGS];
 
 
#define STACKSIZE 8096
#define STACKSIZE 8096
static unsigned char remcomInBuffer[BUFMAX];
static unsigned char remcomInBuffer[BUFMAX];
static unsigned char remcomOutBuffer[BUFMAX];
static unsigned char remcomOutBuffer[BUFMAX];
static int  remcomStack[STACKSIZE/sizeof(int)];
static int  remcomStack[STACKSIZE/sizeof(int)];
static int*  stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
static int*  stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
 
 
static unsigned int save_vectors[18];   /* previous exception vectors */
static unsigned int save_vectors[18];   /* previous exception vectors */
 
 
/* Indicate to caller of mem2hex or hex2mem that there has been an error. */
/* Indicate to caller of mem2hex or hex2mem that there has been an error. */
static volatile int mem_err = 0;
static volatile int mem_err = 0;
 
 
/* Store the vector number here (since GDB only gets the signal
/* Store the vector number here (since GDB only gets the signal
   number through the usual means, and that's not very specific).  */
   number through the usual means, and that's not very specific).  */
int gdb_m32r_vector = -1;
int gdb_m32r_vector = -1;
 
 
#if 0
#if 0
#include "syscall.h" /* for SYS_exit, SYS_write etc. */
#include "syscall.h" /* for SYS_exit, SYS_write etc. */
#endif
#endif
 
 
/* Global entry points:
/* Global entry points:
 */
 */
 
 
extern void handle_exception(int);
extern void handle_exception(int);
extern void set_debug_traps(void);
extern void set_debug_traps(void);
extern void breakpoint(void);
extern void breakpoint(void);
 
 
/* Local functions:
/* Local functions:
 */
 */
 
 
static int  computeSignal(int);
static int  computeSignal(int);
static void putpacket(unsigned char *);
static void putpacket(unsigned char *);
static unsigned char *getpacket(void);
static unsigned char *getpacket(void);
 
 
static unsigned char *mem2hex(unsigned char *, unsigned char *, int, int);
static unsigned char *mem2hex(unsigned char *, unsigned char *, int, int);
static unsigned char *hex2mem(unsigned char *, unsigned char *, int, int);
static unsigned char *hex2mem(unsigned char *, unsigned char *, int, int);
static int  hexToInt(unsigned char **, int *);
static int  hexToInt(unsigned char **, int *);
static unsigned char *bin2mem(unsigned char *, unsigned char *, int, int);
static unsigned char *bin2mem(unsigned char *, unsigned char *, int, int);
static void stash_registers(void);
static void stash_registers(void);
static void restore_registers(void);
static void restore_registers(void);
static int  prepare_to_step(int);
static int  prepare_to_step(int);
static int  finish_from_step(void);
static int  finish_from_step(void);
static unsigned long crc32 (unsigned char *, int, unsigned long);
static unsigned long crc32 (unsigned char *, int, unsigned long);
 
 
static void gdb_error(char *, char *);
static void gdb_error(char *, char *);
static int  gdb_putchar(int), gdb_puts(char *), gdb_write(char *, int);
static int  gdb_putchar(int), gdb_puts(char *), gdb_write(char *, int);
 
 
static unsigned char *strcpy (unsigned char *, const unsigned char *);
static unsigned char *strcpy (unsigned char *, const unsigned char *);
static int   strlen (const unsigned char *);
static int   strlen (const unsigned char *);
 
 
/*
/*
 * This function does all command procesing for interfacing to gdb.
 * This function does all command procesing for interfacing to gdb.
 */
 */
 
 
void
void
handle_exception(int exceptionVector)
handle_exception(int exceptionVector)
{
{
  int    sigval, stepping;
  int    sigval, stepping;
  int    addr, length, i;
  int    addr, length, i;
  unsigned char * ptr;
  unsigned char * ptr;
  unsigned char   buf[16];
  unsigned char   buf[16];
  int binary;
  int binary;
 
 
  if (!finish_from_step())
  if (!finish_from_step())
    return;             /* "false step": let the target continue */
    return;             /* "false step": let the target continue */
 
 
  gdb_m32r_vector = exceptionVector;
  gdb_m32r_vector = exceptionVector;
 
 
  if (remote_debug)
  if (remote_debug)
    {
    {
      mem2hex((unsigned char *) &exceptionVector, buf, 4, 0);
      mem2hex((unsigned char *) &exceptionVector, buf, 4, 0);
      gdb_error("Handle exception %s, ", buf);
      gdb_error("Handle exception %s, ", buf);
      mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
      mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
      gdb_error("PC == 0x%s\n", buf);
      gdb_error("PC == 0x%s\n", buf);
    }
    }
 
 
  /* reply to host that an exception has occurred */
  /* reply to host that an exception has occurred */
  sigval = computeSignal( exceptionVector );
  sigval = computeSignal( exceptionVector );
 
 
  ptr = remcomOutBuffer;
  ptr = remcomOutBuffer;
 
 
  *ptr++ = 'T';         /* notify gdb with signo, PC, FP and SP */
  *ptr++ = 'T';         /* notify gdb with signo, PC, FP and SP */
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval & 0xf];
  *ptr++ = hexchars[sigval & 0xf];
 
 
  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = ':';
  *ptr++ = ':';
  ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);     /* PC */
  ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);     /* PC */
  *ptr++ = ';';
  *ptr++ = ';';
 
 
  *ptr++ = hexchars[R13 >> 4];
  *ptr++ = hexchars[R13 >> 4];
  *ptr++ = hexchars[R13 & 0xf];
  *ptr++ = hexchars[R13 & 0xf];
  *ptr++ = ':';
  *ptr++ = ':';
  ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0);    /* FP */
  ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0);    /* FP */
  *ptr++ = ';';
  *ptr++ = ';';
 
 
  *ptr++ = hexchars[R15 >> 4];
  *ptr++ = hexchars[R15 >> 4];
  *ptr++ = hexchars[R15 & 0xf];
  *ptr++ = hexchars[R15 & 0xf];
  *ptr++ = ':';
  *ptr++ = ':';
  ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0);    /* SP */
  ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0);    /* SP */
  *ptr++ = ';';
  *ptr++ = ';';
  *ptr++ = 0;
  *ptr++ = 0;
 
 
  if (exceptionVector == 0)     /* simulated SYS call stuff */
  if (exceptionVector == 0)     /* simulated SYS call stuff */
    {
    {
      mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
      mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
      switch (registers[R0]) {
      switch (registers[R0]) {
      case SYS_exit:
      case SYS_exit:
        gdb_error("Target program has exited at %s\n", buf);
        gdb_error("Target program has exited at %s\n", buf);
        ptr = remcomOutBuffer;
        ptr = remcomOutBuffer;
        *ptr++ = 'W';
        *ptr++ = 'W';
        sigval = registers[R1] & 0xff;
        sigval = registers[R1] & 0xff;
        *ptr++ = hexchars[sigval >> 4];
        *ptr++ = hexchars[sigval >> 4];
        *ptr++ = hexchars[sigval & 0xf];
        *ptr++ = hexchars[sigval & 0xf];
        *ptr++ = 0;
        *ptr++ = 0;
        break;
        break;
      case SYS_open:
      case SYS_open:
        gdb_error("Target attempts SYS_open call at %s\n", buf);
        gdb_error("Target attempts SYS_open call at %s\n", buf);
        break;
        break;
      case SYS_close:
      case SYS_close:
        gdb_error("Target attempts SYS_close call at %s\n", buf);
        gdb_error("Target attempts SYS_close call at %s\n", buf);
        break;
        break;
      case SYS_read:
      case SYS_read:
        gdb_error("Target attempts SYS_read call at %s\n", buf);
        gdb_error("Target attempts SYS_read call at %s\n", buf);
        break;
        break;
      case SYS_write:
      case SYS_write:
        if (registers[R1] == 1 ||       /* write to stdout  */
        if (registers[R1] == 1 ||       /* write to stdout  */
            registers[R1] == 2)         /* write to stderr  */
            registers[R1] == 2)         /* write to stderr  */
          {                             /* (we can do that) */
          {                             /* (we can do that) */
            registers[R0] = gdb_write((void *) registers[R2], registers[R3]);
            registers[R0] = gdb_write((void *) registers[R2], registers[R3]);
            return;
            return;
          }
          }
        else
        else
          gdb_error("Target attempts SYS_write call at %s\n", buf);
          gdb_error("Target attempts SYS_write call at %s\n", buf);
        break;
        break;
      case SYS_lseek:
      case SYS_lseek:
        gdb_error("Target attempts SYS_lseek call at %s\n", buf);
        gdb_error("Target attempts SYS_lseek call at %s\n", buf);
        break;
        break;
      case SYS_unlink:
      case SYS_unlink:
        gdb_error("Target attempts SYS_unlink call at %s\n", buf);
        gdb_error("Target attempts SYS_unlink call at %s\n", buf);
        break;
        break;
      case SYS_getpid:
      case SYS_getpid:
        gdb_error("Target attempts SYS_getpid call at %s\n", buf);
        gdb_error("Target attempts SYS_getpid call at %s\n", buf);
        break;
        break;
      case SYS_kill:
      case SYS_kill:
        gdb_error("Target attempts SYS_kill call at %s\n", buf);
        gdb_error("Target attempts SYS_kill call at %s\n", buf);
        break;
        break;
      case SYS_fstat:
      case SYS_fstat:
        gdb_error("Target attempts SYS_fstat call at %s\n", buf);
        gdb_error("Target attempts SYS_fstat call at %s\n", buf);
        break;
        break;
      default:
      default:
        gdb_error("Target attempts unknown SYS call at %s\n", buf);
        gdb_error("Target attempts unknown SYS call at %s\n", buf);
        break;
        break;
      }
      }
    }
    }
 
 
  putpacket(remcomOutBuffer);
  putpacket(remcomOutBuffer);
 
 
  stepping = 0;
  stepping = 0;
 
 
  while (1==1) {
  while (1==1) {
    remcomOutBuffer[0] = 0;
    remcomOutBuffer[0] = 0;
    ptr = getpacket();
    ptr = getpacket();
    binary = 0;
    binary = 0;
    switch (*ptr++) {
    switch (*ptr++) {
      default:  /* Unknown code.  Return an empty reply message. */
      default:  /* Unknown code.  Return an empty reply message. */
        break;
        break;
      case 'R':
      case 'R':
        if (hexToInt (&ptr, &addr))
        if (hexToInt (&ptr, &addr))
          registers[PC] = addr;
          registers[PC] = addr;
        strcpy(remcomOutBuffer, "OK");
        strcpy(remcomOutBuffer, "OK");
        break;
        break;
      case '!':
      case '!':
        strcpy(remcomOutBuffer, "OK");
        strcpy(remcomOutBuffer, "OK");
        break;
        break;
    case 'X': /* XAA..AA,LLLL:<binary data>#cs */
    case 'X': /* XAA..AA,LLLL:<binary data>#cs */
      binary = 1;
      binary = 1;
    case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
    case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
      /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
      /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
      {
      {
        if (hexToInt(&ptr,&addr))
        if (hexToInt(&ptr,&addr))
          if (*(ptr++) == ',')
          if (*(ptr++) == ',')
            if (hexToInt(&ptr,&length))
            if (hexToInt(&ptr,&length))
              if (*(ptr++) == ':')
              if (*(ptr++) == ':')
                {
                {
                  mem_err = 0;
                  mem_err = 0;
                  if (binary)
                  if (binary)
                    bin2mem (ptr, (unsigned char *) addr, length, 1);
                    bin2mem (ptr, (unsigned char *) addr, length, 1);
                  else
                  else
                    hex2mem(ptr, (unsigned char*) addr, length, 1);
                    hex2mem(ptr, (unsigned char*) addr, length, 1);
                  if (mem_err) {
                  if (mem_err) {
                    strcpy (remcomOutBuffer, "E03");
                    strcpy (remcomOutBuffer, "E03");
                    gdb_error ("memory fault", "");
                    gdb_error ("memory fault", "");
                  } else {
                  } else {
                    strcpy(remcomOutBuffer,"OK");
                    strcpy(remcomOutBuffer,"OK");
                  }
                  }
                  ptr = 0;
                  ptr = 0;
                }
                }
        if (ptr)
        if (ptr)
          {
          {
            strcpy(remcomOutBuffer,"E02");
            strcpy(remcomOutBuffer,"E02");
          }
          }
      }
      }
        break;
        break;
      case 'm': /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
      case 'm': /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
                /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
                /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
        if (hexToInt(&ptr,&addr))
        if (hexToInt(&ptr,&addr))
          if (*(ptr++) == ',')
          if (*(ptr++) == ',')
            if (hexToInt(&ptr,&length))
            if (hexToInt(&ptr,&length))
              {
              {
                ptr = 0;
                ptr = 0;
                mem_err = 0;
                mem_err = 0;
                mem2hex((unsigned char*) addr, remcomOutBuffer, length, 1);
                mem2hex((unsigned char*) addr, remcomOutBuffer, length, 1);
                if (mem_err) {
                if (mem_err) {
                  strcpy (remcomOutBuffer, "E03");
                  strcpy (remcomOutBuffer, "E03");
                  gdb_error ("memory fault", "");
                  gdb_error ("memory fault", "");
                }
                }
              }
              }
        if (ptr)
        if (ptr)
          {
          {
            strcpy(remcomOutBuffer,"E01");
            strcpy(remcomOutBuffer,"E01");
          }
          }
        break;
        break;
      case '?':
      case '?':
        remcomOutBuffer[0] = 'S';
        remcomOutBuffer[0] = 'S';
        remcomOutBuffer[1] =  hexchars[sigval >> 4];
        remcomOutBuffer[1] =  hexchars[sigval >> 4];
        remcomOutBuffer[2] =  hexchars[sigval % 16];
        remcomOutBuffer[2] =  hexchars[sigval % 16];
        remcomOutBuffer[3] = 0;
        remcomOutBuffer[3] = 0;
        break;
        break;
      case 'd':
      case 'd':
        remote_debug = !(remote_debug);  /* toggle debug flag */
        remote_debug = !(remote_debug);  /* toggle debug flag */
        break;
        break;
      case 'g': /* return the value of the CPU registers */
      case 'g': /* return the value of the CPU registers */
        mem2hex((unsigned char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
        mem2hex((unsigned char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
        break;
        break;
      case 'P': /* set the value of a single CPU register - return OK */
      case 'P': /* set the value of a single CPU register - return OK */
        {
        {
          int regno;
          int regno;
 
 
          if (hexToInt (&ptr, &regno) && *ptr++ == '=')
          if (hexToInt (&ptr, &regno) && *ptr++ == '=')
            if (regno >= 0 && regno < NUMREGS)
            if (regno >= 0 && regno < NUMREGS)
              {
              {
                int stackmode;
                int stackmode;
 
 
                hex2mem (ptr, (unsigned char *) &registers[regno], 4, 0);
                hex2mem (ptr, (unsigned char *) &registers[regno], 4, 0);
                /*
                /*
                 * Since we just changed a single CPU register, let's
                 * Since we just changed a single CPU register, let's
                 * make sure to keep the several stack pointers consistant.
                 * make sure to keep the several stack pointers consistant.
                 */
                 */
                stackmode = registers[PSW] & 0x80;
                stackmode = registers[PSW] & 0x80;
                if (regno == R15)       /* stack pointer changed */
                if (regno == R15)       /* stack pointer changed */
                  {                     /* need to change SPI or SPU */
                  {                     /* need to change SPI or SPU */
                    if (stackmode == 0)
                    if (stackmode == 0)
                      registers[SPI] = registers[R15];
                      registers[SPI] = registers[R15];
                    else
                    else
                      registers[SPU] = registers[R15];
                      registers[SPU] = registers[R15];
                  }
                  }
                else if (regno == SPU)  /* "user" stack pointer changed */
                else if (regno == SPU)  /* "user" stack pointer changed */
                  {
                  {
                    if (stackmode != 0)  /* stack in user mode: copy SP */
                    if (stackmode != 0)  /* stack in user mode: copy SP */
                      registers[R15] = registers[SPU];
                      registers[R15] = registers[SPU];
                  }
                  }
                else if (regno == SPI)  /* "interrupt" stack pointer changed */
                else if (regno == SPI)  /* "interrupt" stack pointer changed */
                  {
                  {
                    if (stackmode == 0)  /* stack in interrupt mode: copy SP */
                    if (stackmode == 0)  /* stack in interrupt mode: copy SP */
                      registers[R15] = registers[SPI];
                      registers[R15] = registers[SPI];
                  }
                  }
                else if (regno == PSW)  /* stack mode may have changed! */
                else if (regno == PSW)  /* stack mode may have changed! */
                  {                     /* force SP to either SPU or SPI */
                  {                     /* force SP to either SPU or SPI */
                    if (stackmode == 0)  /* stack in user mode */
                    if (stackmode == 0)  /* stack in user mode */
                      registers[R15] = registers[SPI];
                      registers[R15] = registers[SPI];
                    else                /* stack in interrupt mode */
                    else                /* stack in interrupt mode */
                      registers[R15] = registers[SPU];
                      registers[R15] = registers[SPU];
                  }
                  }
                strcpy (remcomOutBuffer, "OK");
                strcpy (remcomOutBuffer, "OK");
                break;
                break;
              }
              }
          strcpy (remcomOutBuffer, "E01");
          strcpy (remcomOutBuffer, "E01");
          break;
          break;
        }
        }
      case 'G': /* set the value of the CPU registers - return OK */
      case 'G': /* set the value of the CPU registers - return OK */
        hex2mem(ptr, (unsigned char*) registers, NUMREGBYTES, 0);
        hex2mem(ptr, (unsigned char*) registers, NUMREGBYTES, 0);
        strcpy(remcomOutBuffer,"OK");
        strcpy(remcomOutBuffer,"OK");
        break;
        break;
      case 's': /* sAA..AA      Step one instruction from AA..AA(optional) */
      case 's': /* sAA..AA      Step one instruction from AA..AA(optional) */
        stepping = 1;
        stepping = 1;
      case 'c': /* cAA..AA      Continue from address AA..AA(optional) */
      case 'c': /* cAA..AA      Continue from address AA..AA(optional) */
                /* try to read optional parameter, pc unchanged if no parm */
                /* try to read optional parameter, pc unchanged if no parm */
        if (hexToInt(&ptr,&addr))
        if (hexToInt(&ptr,&addr))
          registers[ PC ] = addr;
          registers[ PC ] = addr;
 
 
        if (stepping)   /* single-stepping */
        if (stepping)   /* single-stepping */
          {
          {
            if (!prepare_to_step(0))     /* set up for single-step */
            if (!prepare_to_step(0))     /* set up for single-step */
              {
              {
                /* prepare_to_step has already emulated the target insn:
                /* prepare_to_step has already emulated the target insn:
                   Send SIGTRAP to gdb, don't resume the target at all.  */
                   Send SIGTRAP to gdb, don't resume the target at all.  */
                ptr = remcomOutBuffer;
                ptr = remcomOutBuffer;
                *ptr++ = 'T';           /* Simulate stopping with SIGTRAP */
                *ptr++ = 'T';           /* Simulate stopping with SIGTRAP */
                *ptr++ = '0';
                *ptr++ = '0';
                *ptr++ = '5';
                *ptr++ = '5';
 
 
                *ptr++ = hexchars[PC >> 4];     /* send PC */
                *ptr++ = hexchars[PC >> 4];     /* send PC */
                *ptr++ = hexchars[PC & 0xf];
                *ptr++ = hexchars[PC & 0xf];
                *ptr++ = ':';
                *ptr++ = ':';
                ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
                ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
                *ptr++ = ';';
                *ptr++ = ';';
 
 
                *ptr++ = hexchars[R13 >> 4];    /* send FP */
                *ptr++ = hexchars[R13 >> 4];    /* send FP */
                *ptr++ = hexchars[R13 & 0xf];
                *ptr++ = hexchars[R13 & 0xf];
                *ptr++ = ':';
                *ptr++ = ':';
                ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0);
                ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0);
                *ptr++ = ';';
                *ptr++ = ';';
 
 
                *ptr++ = hexchars[R15 >> 4];    /* send SP */
                *ptr++ = hexchars[R15 >> 4];    /* send SP */
                *ptr++ = hexchars[R15 & 0xf];
                *ptr++ = hexchars[R15 & 0xf];
                *ptr++ = ':';
                *ptr++ = ':';
                ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0);
                ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0);
                *ptr++ = ';';
                *ptr++ = ';';
                *ptr++ = 0;
                *ptr++ = 0;
 
 
                break;
                break;
              }
              }
          }
          }
        else    /* continuing, not single-stepping */
        else    /* continuing, not single-stepping */
          {
          {
            /* OK, about to do a "continue".  First check to see if the
            /* OK, about to do a "continue".  First check to see if the
               target pc is on an odd boundary (second instruction in the
               target pc is on an odd boundary (second instruction in the
               word).  If so, we must do a single-step first, because
               word).  If so, we must do a single-step first, because
               ya can't jump or return back to an odd boundary!  */
               ya can't jump or return back to an odd boundary!  */
            if ((registers[PC] & 2) != 0)
            if ((registers[PC] & 2) != 0)
              prepare_to_step(1);
              prepare_to_step(1);
          }
          }
 
 
        return;
        return;
 
 
      case 'D': /* Detach */
      case 'D': /* Detach */
#if 0
#if 0
        /* I am interpreting this to mean, release the board from control
        /* I am interpreting this to mean, release the board from control
           by the remote stub.  To do this, I am restoring the original
           by the remote stub.  To do this, I am restoring the original
           (or at least previous) exception vectors.
           (or at least previous) exception vectors.
         */
         */
        for (i = 0; i < 18; i++)
        for (i = 0; i < 18; i++)
          exceptionHandler (i, save_vectors[i]);
          exceptionHandler (i, save_vectors[i]);
        putpacket ("OK");
        putpacket ("OK");
        return;         /* continue the inferior */
        return;         /* continue the inferior */
#else
#else
        strcpy(remcomOutBuffer,"OK");
        strcpy(remcomOutBuffer,"OK");
        break;
        break;
#endif
#endif
    case 'q':
    case 'q':
      if (*ptr++ == 'C' &&
      if (*ptr++ == 'C' &&
          *ptr++ == 'R' &&
          *ptr++ == 'R' &&
          *ptr++ == 'C' &&
          *ptr++ == 'C' &&
          *ptr++ == ':')
          *ptr++ == ':')
        {
        {
          unsigned long start, len, our_crc;
          unsigned long start, len, our_crc;
 
 
          if (hexToInt (&ptr, (int *) &start) &&
          if (hexToInt (&ptr, (int *) &start) &&
              *ptr++ == ','                   &&
              *ptr++ == ','                   &&
              hexToInt (&ptr, (int *) &len))
              hexToInt (&ptr, (int *) &len))
            {
            {
              remcomOutBuffer[0] = 'C';
              remcomOutBuffer[0] = 'C';
              our_crc = crc32 ((unsigned char *) start, len, 0xffffffff);
              our_crc = crc32 ((unsigned char *) start, len, 0xffffffff);
              mem2hex ((char *) &our_crc,
              mem2hex ((char *) &our_crc,
                       &remcomOutBuffer[1],
                       &remcomOutBuffer[1],
                       sizeof (long),
                       sizeof (long),
                       0);
                       0);
            } /* else do nothing */
            } /* else do nothing */
        } /* else do nothing */
        } /* else do nothing */
      break;
      break;
 
 
      case 'k': /* kill the program */
      case 'k': /* kill the program */
        continue;
        continue;
      } /* switch */
      } /* switch */
 
 
    /* reply to the request */
    /* reply to the request */
    putpacket(remcomOutBuffer);
    putpacket(remcomOutBuffer);
  }
  }
}
}
 
 
/* qCRC support */
/* qCRC support */
 
 
/* Table used by the crc32 function to calcuate the checksum. */
/* Table used by the crc32 function to calcuate the checksum. */
static unsigned long crc32_table[256] = {0, 0};
static unsigned long crc32_table[256] = {0, 0};
 
 
static unsigned long
static unsigned long
crc32 (buf, len, crc)
crc32 (buf, len, crc)
     unsigned char *buf;
     unsigned char *buf;
     int len;
     int len;
     unsigned long crc;
     unsigned long crc;
{
{
  if (! crc32_table[1])
  if (! crc32_table[1])
    {
    {
      /* Initialize the CRC table and the decoding table. */
      /* Initialize the CRC table and the decoding table. */
      int i, j;
      int i, j;
      unsigned long c;
      unsigned long c;
 
 
      for (i = 0; i < 256; i++)
      for (i = 0; i < 256; i++)
        {
        {
          for (c = i << 24, j = 8; j > 0; --j)
          for (c = i << 24, j = 8; j > 0; --j)
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
          crc32_table[i] = c;
          crc32_table[i] = c;
        }
        }
    }
    }
 
 
  while (len--)
  while (len--)
    {
    {
      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
      buf++;
      buf++;
    }
    }
  return crc;
  return crc;
}
}
 
 
static int
static int
hex(ch)
hex(ch)
     unsigned char ch;
     unsigned char ch;
{
{
  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
  return (-1);
  return (-1);
}
}
 
 
/* scan for the sequence $<data>#<checksum>     */
/* scan for the sequence $<data>#<checksum>     */
 
 
unsigned char *
unsigned char *
getpacket ()
getpacket ()
{
{
  unsigned char *buffer = &remcomInBuffer[0];
  unsigned char *buffer = &remcomInBuffer[0];
  unsigned char checksum;
  unsigned char checksum;
  unsigned char xmitcsum;
  unsigned char xmitcsum;
  int count;
  int count;
  char ch;
  char ch;
 
 
  while (1)
  while (1)
    {
    {
      /* wait around for the start character, ignore all other characters */
      /* wait around for the start character, ignore all other characters */
      while ((ch = getDebugChar ()) != '$')
      while ((ch = getDebugChar ()) != '$')
        ;
        ;
 
 
retry:
retry:
      checksum = 0;
      checksum = 0;
      xmitcsum = -1;
      xmitcsum = -1;
      count = 0;
      count = 0;
 
 
      /* now, read until a # or end of buffer is found */
      /* now, read until a # or end of buffer is found */
      while (count < BUFMAX)
      while (count < BUFMAX)
        {
        {
          ch = getDebugChar ();
          ch = getDebugChar ();
          if (ch == '$')
          if (ch == '$')
            goto retry;
            goto retry;
          if (ch == '#')
          if (ch == '#')
            break;
            break;
          checksum = checksum + ch;
          checksum = checksum + ch;
          buffer[count] = ch;
          buffer[count] = ch;
          count = count + 1;
          count = count + 1;
        }
        }
      buffer[count] = 0;
      buffer[count] = 0;
 
 
      if (ch == '#')
      if (ch == '#')
        {
        {
          ch = getDebugChar ();
          ch = getDebugChar ();
          xmitcsum = hex (ch) << 4;
          xmitcsum = hex (ch) << 4;
          ch = getDebugChar ();
          ch = getDebugChar ();
          xmitcsum += hex (ch);
          xmitcsum += hex (ch);
 
 
          if (checksum != xmitcsum)
          if (checksum != xmitcsum)
            {
            {
              if (remote_debug)
              if (remote_debug)
                {
                {
                  unsigned char buf[16];
                  unsigned char buf[16];
 
 
                  mem2hex((unsigned char *) &checksum, buf, 4, 0);
                  mem2hex((unsigned char *) &checksum, buf, 4, 0);
                  gdb_error("Bad checksum: my count = %s, ", buf);
                  gdb_error("Bad checksum: my count = %s, ", buf);
                  mem2hex((unsigned char *) &xmitcsum, buf, 4, 0);
                  mem2hex((unsigned char *) &xmitcsum, buf, 4, 0);
                  gdb_error("sent count = %s\n", buf);
                  gdb_error("sent count = %s\n", buf);
                  gdb_error(" -- Bad buffer: \"%s\"\n", buffer);
                  gdb_error(" -- Bad buffer: \"%s\"\n", buffer);
                }
                }
              putDebugChar ('-');       /* failed checksum */
              putDebugChar ('-');       /* failed checksum */
            }
            }
          else
          else
            {
            {
              putDebugChar ('+');       /* successful transfer */
              putDebugChar ('+');       /* successful transfer */
 
 
              /* if a sequence char is present, reply the sequence ID */
              /* if a sequence char is present, reply the sequence ID */
              if (buffer[2] == ':')
              if (buffer[2] == ':')
                {
                {
                  putDebugChar (buffer[0]);
                  putDebugChar (buffer[0]);
                  putDebugChar (buffer[1]);
                  putDebugChar (buffer[1]);
 
 
                  return &buffer[3];
                  return &buffer[3];
                }
                }
 
 
              return &buffer[0];
              return &buffer[0];
            }
            }
        }
        }
    }
    }
}
}
 
 
/* send the packet in buffer.  */
/* send the packet in buffer.  */
 
 
static void
static void
putpacket(buffer)
putpacket(buffer)
     unsigned char *buffer;
     unsigned char *buffer;
{
{
  unsigned char checksum;
  unsigned char checksum;
  int  count;
  int  count;
  char ch;
  char ch;
 
 
  /*  $<packet info>#<checksum>. */
  /*  $<packet info>#<checksum>. */
  do {
  do {
    putDebugChar('$');
    putDebugChar('$');
    checksum = 0;
    checksum = 0;
    count    = 0;
    count    = 0;
 
 
    while (ch=buffer[count]) {
    while (ch=buffer[count]) {
      putDebugChar(ch);
      putDebugChar(ch);
      checksum += ch;
      checksum += ch;
      count += 1;
      count += 1;
    }
    }
    putDebugChar('#');
    putDebugChar('#');
    putDebugChar(hexchars[checksum >> 4]);
    putDebugChar(hexchars[checksum >> 4]);
    putDebugChar(hexchars[checksum % 16]);
    putDebugChar(hexchars[checksum % 16]);
  } while (getDebugChar() != '+');
  } while (getDebugChar() != '+');
}
}
 
 
/* Address of a routine to RTE to if we get a memory fault.  */
/* Address of a routine to RTE to if we get a memory fault.  */
 
 
static void (*volatile mem_fault_routine)() = 0;
static void (*volatile mem_fault_routine)() = 0;
 
 
static void
static void
set_mem_err ()
set_mem_err ()
{
{
  mem_err = 1;
  mem_err = 1;
}
}
 
 
/* Check the address for safe access ranges.  As currently defined,
/* Check the address for safe access ranges.  As currently defined,
   this routine will reject the "expansion bus" address range(s).
   this routine will reject the "expansion bus" address range(s).
   To make those ranges useable, someone must implement code to detect
   To make those ranges useable, someone must implement code to detect
   whether there's anything connected to the expansion bus. */
   whether there's anything connected to the expansion bus. */
 
 
static int
static int
mem_safe (addr)
mem_safe (addr)
     unsigned char *addr;
     unsigned char *addr;
{
{
#define BAD_RANGE_ONE_START     ((unsigned char *) 0x600000)
#define BAD_RANGE_ONE_START     ((unsigned char *) 0x600000)
#define BAD_RANGE_ONE_END       ((unsigned char *) 0xa00000)
#define BAD_RANGE_ONE_END       ((unsigned char *) 0xa00000)
#define BAD_RANGE_TWO_START     ((unsigned char *) 0xff680000)
#define BAD_RANGE_TWO_START     ((unsigned char *) 0xff680000)
#define BAD_RANGE_TWO_END       ((unsigned char *) 0xff800000)
#define BAD_RANGE_TWO_END       ((unsigned char *) 0xff800000)
 
 
  if (addr < BAD_RANGE_ONE_START)       return 1;       /* safe */
  if (addr < BAD_RANGE_ONE_START)       return 1;       /* safe */
  if (addr < BAD_RANGE_ONE_END)         return 0;        /* unsafe */
  if (addr < BAD_RANGE_ONE_END)         return 0;        /* unsafe */
  if (addr < BAD_RANGE_TWO_START)       return 1;       /* safe */
  if (addr < BAD_RANGE_TWO_START)       return 1;       /* safe */
  if (addr < BAD_RANGE_TWO_END)         return 0;        /* unsafe */
  if (addr < BAD_RANGE_TWO_END)         return 0;        /* unsafe */
}
}
 
 
/* These are separate functions so that they are so short and sweet
/* These are separate functions so that they are so short and sweet
   that the compiler won't save any registers (if there is a fault
   that the compiler won't save any registers (if there is a fault
   to mem_fault, they won't get restored, so there better not be any
   to mem_fault, they won't get restored, so there better not be any
   saved).  */
   saved).  */
static int
static int
get_char (addr)
get_char (addr)
     unsigned char *addr;
     unsigned char *addr;
{
{
#if 1
#if 1
  if (mem_fault_routine && !mem_safe(addr))
  if (mem_fault_routine && !mem_safe(addr))
    {
    {
      mem_fault_routine ();
      mem_fault_routine ();
      return 0;
      return 0;
    }
    }
#endif
#endif
  return *addr;
  return *addr;
}
}
 
 
static void
static void
set_char (addr, val)
set_char (addr, val)
     unsigned char *addr;
     unsigned char *addr;
     unsigned char val;
     unsigned char val;
{
{
#if 1
#if 1
  if (mem_fault_routine && !mem_safe (addr))
  if (mem_fault_routine && !mem_safe (addr))
    {
    {
      mem_fault_routine ();
      mem_fault_routine ();
      return;
      return;
    }
    }
#endif
#endif
  *addr = val;
  *addr = val;
}
}
 
 
/* Convert the memory pointed to by mem into hex, placing result in buf.
/* Convert the memory pointed to by mem into hex, placing result in buf.
   Return a pointer to the last char put in buf (null).
   Return a pointer to the last char put in buf (null).
   If MAY_FAULT is non-zero, then we should set mem_err in response to
   If MAY_FAULT is non-zero, then we should set mem_err in response to
   a fault; if zero treat a fault like any other fault in the stub.  */
   a fault; if zero treat a fault like any other fault in the stub.  */
 
 
static unsigned char *
static unsigned char *
mem2hex(mem, buf, count, may_fault)
mem2hex(mem, buf, count, may_fault)
     unsigned char* mem;
     unsigned char* mem;
     unsigned char* buf;
     unsigned char* buf;
     int   count;
     int   count;
     int   may_fault;
     int   may_fault;
{
{
  int i;
  int i;
  unsigned char ch;
  unsigned char ch;
 
 
  if (may_fault)
  if (may_fault)
    mem_fault_routine = set_mem_err;
    mem_fault_routine = set_mem_err;
  for (i=0;i<count;i++) {
  for (i=0;i<count;i++) {
    ch = get_char (mem++);
    ch = get_char (mem++);
    if (may_fault && mem_err)
    if (may_fault && mem_err)
      return (buf);
      return (buf);
    *buf++ = hexchars[ch >> 4];
    *buf++ = hexchars[ch >> 4];
    *buf++ = hexchars[ch % 16];
    *buf++ = hexchars[ch % 16];
  }
  }
  *buf = 0;
  *buf = 0;
  if (may_fault)
  if (may_fault)
    mem_fault_routine = 0;
    mem_fault_routine = 0;
  return(buf);
  return(buf);
}
}
 
 
/* Convert the hex array pointed to by buf into binary to be placed in mem.
/* 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. */
   Return a pointer to the character AFTER the last byte written. */
 
 
static unsigned char*
static unsigned char*
hex2mem(buf, mem, count, may_fault)
hex2mem(buf, mem, count, may_fault)
     unsigned char* buf;
     unsigned char* buf;
     unsigned char* mem;
     unsigned char* mem;
     int   count;
     int   count;
     int   may_fault;
     int   may_fault;
{
{
  int i;
  int i;
  unsigned char ch;
  unsigned char ch;
 
 
  if (may_fault)
  if (may_fault)
    mem_fault_routine = set_mem_err;
    mem_fault_routine = set_mem_err;
  for (i=0;i<count;i++) {
  for (i=0;i<count;i++) {
    ch = hex(*buf++) << 4;
    ch = hex(*buf++) << 4;
    ch = ch + hex(*buf++);
    ch = ch + hex(*buf++);
    set_char (mem++, ch);
    set_char (mem++, ch);
    if (may_fault && mem_err)
    if (may_fault && mem_err)
      return (mem);
      return (mem);
  }
  }
  if (may_fault)
  if (may_fault)
    mem_fault_routine = 0;
    mem_fault_routine = 0;
  return(mem);
  return(mem);
}
}
 
 
/* Convert the binary stream in BUF to memory.
/* Convert the binary stream in BUF to memory.
 
 
   Gdb will escape $, #, and the escape char (0x7d).
   Gdb will escape $, #, and the escape char (0x7d).
   COUNT is the total number of bytes to write into
   COUNT is the total number of bytes to write into
   memory. */
   memory. */
static unsigned char *
static unsigned char *
bin2mem (buf, mem, count, may_fault)
bin2mem (buf, mem, count, may_fault)
     unsigned char *buf;
     unsigned char *buf;
     unsigned char *mem;
     unsigned char *mem;
     int   count;
     int   count;
     int   may_fault;
     int   may_fault;
{
{
  int i;
  int i;
  unsigned char ch;
  unsigned char ch;
 
 
  if (may_fault)
  if (may_fault)
    mem_fault_routine = set_mem_err;
    mem_fault_routine = set_mem_err;
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      /* Check for any escaped characters. Be paranoid and
      /* Check for any escaped characters. Be paranoid and
         only unescape chars that should be escaped. */
         only unescape chars that should be escaped. */
      if (*buf == 0x7d)
      if (*buf == 0x7d)
        {
        {
          switch (*(buf+1))
          switch (*(buf+1))
            {
            {
            case 0x3:  /* # */
            case 0x3:  /* # */
            case 0x4:  /* $ */
            case 0x4:  /* $ */
            case 0x5d: /* escape char */
            case 0x5d: /* escape char */
              buf++;
              buf++;
              *buf |= 0x20;
              *buf |= 0x20;
              break;
              break;
            default:
            default:
              /* nothing */
              /* nothing */
              break;
              break;
            }
            }
        }
        }
 
 
      set_char (mem++, *buf++);
      set_char (mem++, *buf++);
 
 
      if (may_fault && mem_err)
      if (may_fault && mem_err)
        return mem;
        return mem;
    }
    }
 
 
  if (may_fault)
  if (may_fault)
    mem_fault_routine = 0;
    mem_fault_routine = 0;
  return mem;
  return mem;
}
}
 
 
/* this function takes the m32r exception vector and attempts to
/* this function takes the m32r exception vector and attempts to
   translate this number into a unix compatible signal value */
   translate this number into a unix compatible signal value */
 
 
static int
static int
computeSignal(exceptionVector)
computeSignal(exceptionVector)
     int exceptionVector;
     int exceptionVector;
{
{
  int sigval;
  int sigval;
  switch (exceptionVector) {
  switch (exceptionVector) {
    case 0  : sigval = 23; break; /* I/O trap                    */
    case 0  : sigval = 23; break; /* I/O trap                    */
    case 1  : sigval = 5;  break; /* breakpoint                  */
    case 1  : sigval = 5;  break; /* breakpoint                  */
    case 2  : sigval = 5;  break; /* breakpoint                  */
    case 2  : sigval = 5;  break; /* breakpoint                  */
    case 3  : sigval = 5;  break; /* breakpoint                  */
    case 3  : sigval = 5;  break; /* breakpoint                  */
    case 4  : sigval = 5;  break; /* breakpoint                  */
    case 4  : sigval = 5;  break; /* breakpoint                  */
    case 5  : sigval = 5;  break; /* breakpoint                  */
    case 5  : sigval = 5;  break; /* breakpoint                  */
    case 6  : sigval = 5;  break; /* breakpoint                  */
    case 6  : sigval = 5;  break; /* breakpoint                  */
    case 7  : sigval = 5;  break; /* breakpoint                  */
    case 7  : sigval = 5;  break; /* breakpoint                  */
    case 8  : sigval = 5;  break; /* breakpoint                  */
    case 8  : sigval = 5;  break; /* breakpoint                  */
    case 9  : sigval = 5;  break; /* breakpoint                  */
    case 9  : sigval = 5;  break; /* breakpoint                  */
    case 10 : sigval = 5;  break; /* breakpoint                  */
    case 10 : sigval = 5;  break; /* breakpoint                  */
    case 11 : sigval = 5;  break; /* breakpoint                  */
    case 11 : sigval = 5;  break; /* breakpoint                  */
    case 12 : sigval = 5;  break; /* breakpoint                  */
    case 12 : sigval = 5;  break; /* breakpoint                  */
    case 13 : sigval = 5;  break; /* breakpoint                  */
    case 13 : sigval = 5;  break; /* breakpoint                  */
    case 14 : sigval = 5;  break; /* breakpoint                  */
    case 14 : sigval = 5;  break; /* breakpoint                  */
    case 15 : sigval = 5;  break; /* breakpoint                  */
    case 15 : sigval = 5;  break; /* breakpoint                  */
    case 16 : sigval = 10; break; /* BUS ERROR (alignment)       */
    case 16 : sigval = 10; break; /* BUS ERROR (alignment)       */
    case 17 : sigval = 2;  break; /* INTerrupt                   */
    case 17 : sigval = 2;  break; /* INTerrupt                   */
    default : sigval = 7;  break; /* "software generated"        */
    default : sigval = 7;  break; /* "software generated"        */
  }
  }
  return (sigval);
  return (sigval);
}
}
 
 
/**********************************************/
/**********************************************/
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
/* RETURN NUMBER OF CHARS PROCESSED           */
/* RETURN NUMBER OF CHARS PROCESSED           */
/**********************************************/
/**********************************************/
static int
static int
hexToInt(ptr, intValue)
hexToInt(ptr, intValue)
     unsigned char **ptr;
     unsigned char **ptr;
     int *intValue;
     int *intValue;
{
{
  int numChars = 0;
  int numChars = 0;
  int hexValue;
  int hexValue;
 
 
  *intValue = 0;
  *intValue = 0;
  while (**ptr)
  while (**ptr)
    {
    {
      hexValue = hex(**ptr);
      hexValue = hex(**ptr);
      if (hexValue >=0)
      if (hexValue >=0)
        {
        {
          *intValue = (*intValue <<4) | hexValue;
          *intValue = (*intValue <<4) | hexValue;
          numChars ++;
          numChars ++;
        }
        }
      else
      else
        break;
        break;
      (*ptr)++;
      (*ptr)++;
    }
    }
  return (numChars);
  return (numChars);
}
}
 
 
/*
/*
  Table of branch instructions:
  Table of branch instructions:
 
 
  10B6          RTE     return from trap or exception
  10B6          RTE     return from trap or exception
  1FCr          JMP     jump
  1FCr          JMP     jump
  1ECr          JL      jump and link
  1ECr          JL      jump and link
  7Fxx          BRA     branch
  7Fxx          BRA     branch
  FFxxxxxx      BRA     branch (long)
  FFxxxxxx      BRA     branch (long)
  B09rxxxx      BNEZ    branch not-equal-zero
  B09rxxxx      BNEZ    branch not-equal-zero
  Br1rxxxx      BNE     branch not-equal
  Br1rxxxx      BNE     branch not-equal
  7Dxx          BNC     branch not-condition
  7Dxx          BNC     branch not-condition
  FDxxxxxx      BNC     branch not-condition (long)
  FDxxxxxx      BNC     branch not-condition (long)
  B0Arxxxx      BLTZ    branch less-than-zero
  B0Arxxxx      BLTZ    branch less-than-zero
  B0Crxxxx      BLEZ    branch less-equal-zero
  B0Crxxxx      BLEZ    branch less-equal-zero
  7Exx          BL      branch and link
  7Exx          BL      branch and link
  FExxxxxx      BL      branch and link (long)
  FExxxxxx      BL      branch and link (long)
  B0Drxxxx      BGTZ    branch greater-than-zero
  B0Drxxxx      BGTZ    branch greater-than-zero
  B0Brxxxx      BGEZ    branch greater-equal-zero
  B0Brxxxx      BGEZ    branch greater-equal-zero
  B08rxxxx      BEQZ    branch equal-zero
  B08rxxxx      BEQZ    branch equal-zero
  Br0rxxxx      BEQ     branch equal
  Br0rxxxx      BEQ     branch equal
  7Cxx          BC      branch condition
  7Cxx          BC      branch condition
  FCxxxxxx      BC      branch condition (long)
  FCxxxxxx      BC      branch condition (long)
  */
  */
 
 
static int
static int
isShortBranch(instr)
isShortBranch(instr)
     unsigned char *instr;
     unsigned char *instr;
{
{
  unsigned char instr0 = instr[0] & 0x7F;                /* mask off high bit */
  unsigned char instr0 = instr[0] & 0x7F;                /* mask off high bit */
 
 
  if (instr0 == 0x10 && instr[1] == 0xB6)       /* RTE */
  if (instr0 == 0x10 && instr[1] == 0xB6)       /* RTE */
    return 1;           /* return from trap or exception */
    return 1;           /* return from trap or exception */
 
 
  if (instr0 == 0x1E || instr0 == 0x1F)         /* JL or JMP */
  if (instr0 == 0x1E || instr0 == 0x1F)         /* JL or JMP */
    if ((instr[1] & 0xF0) == 0xC0)
    if ((instr[1] & 0xF0) == 0xC0)
      return 2;                                 /* jump thru a register */
      return 2;                                 /* jump thru a register */
 
 
  if (instr0 == 0x7C || instr0 == 0x7D ||       /* BC, BNC, BL, BRA */
  if (instr0 == 0x7C || instr0 == 0x7D ||       /* BC, BNC, BL, BRA */
      instr0 == 0x7E || instr0 == 0x7F)
      instr0 == 0x7E || instr0 == 0x7F)
    return 3;                                   /* eight bit PC offset */
    return 3;                                   /* eight bit PC offset */
 
 
  return 0;
  return 0;
}
}
 
 
static int
static int
isLongBranch(instr)
isLongBranch(instr)
     unsigned char *instr;
     unsigned char *instr;
{
{
  if (instr[0] == 0xFC || instr[0] == 0xFD ||     /* BRA, BNC, BL, BC */
  if (instr[0] == 0xFC || instr[0] == 0xFD ||     /* BRA, BNC, BL, BC */
      instr[0] == 0xFE || instr[0] == 0xFF)       /* 24 bit relative */
      instr[0] == 0xFE || instr[0] == 0xFF)       /* 24 bit relative */
    return 4;
    return 4;
  if ((instr[0] & 0xF0) == 0xB0)         /* 16 bit relative */
  if ((instr[0] & 0xF0) == 0xB0)         /* 16 bit relative */
    {
    {
      if ((instr[1] & 0xF0) == 0x00 ||          /* BNE, BEQ */
      if ((instr[1] & 0xF0) == 0x00 ||          /* BNE, BEQ */
          (instr[1] & 0xF0) == 0x10)
          (instr[1] & 0xF0) == 0x10)
        return 5;
        return 5;
      if (instr[0] == 0xB0)      /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
      if (instr[0] == 0xB0)      /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
        if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
        if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
            (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
            (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
            (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
            (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
          return 6;
          return 6;
    }
    }
  return 0;
  return 0;
}
}
 
 
/* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
/* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
   then it's a 2-byte instruction, else it's a 4-byte instruction.  */
   then it's a 2-byte instruction, else it's a 4-byte instruction.  */
 
 
#define INSTRUCTION_SIZE(addr) \
#define INSTRUCTION_SIZE(addr) \
    ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
    ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
 
 
static int
static int
isBranch(instr)
isBranch(instr)
     unsigned char *instr;
     unsigned char *instr;
{
{
  if (INSTRUCTION_SIZE(instr) == 2)
  if (INSTRUCTION_SIZE(instr) == 2)
    return isShortBranch(instr);
    return isShortBranch(instr);
  else
  else
    return isLongBranch(instr);
    return isLongBranch(instr);
}
}
 
 
static int
static int
willBranch(instr, branchCode)
willBranch(instr, branchCode)
     unsigned char *instr;
     unsigned char *instr;
{
{
  switch (branchCode)
  switch (branchCode)
    {
    {
    case 0:      return 0;        /* not a branch */
    case 0:      return 0;        /* not a branch */
    case 1:     return 1;       /* RTE */
    case 1:     return 1;       /* RTE */
    case 2:     return 1;       /* JL or JMP    */
    case 2:     return 1;       /* JL or JMP    */
    case 3:                     /* BC, BNC, BL, BRA (short) */
    case 3:                     /* BC, BNC, BL, BRA (short) */
    case 4:                     /* BC, BNC, BL, BRA (long) */
    case 4:                     /* BC, BNC, BL, BRA (long) */
      switch (instr[0] & 0x0F)
      switch (instr[0] & 0x0F)
        {
        {
        case 0xC:               /* Branch if Condition Register */
        case 0xC:               /* Branch if Condition Register */
          return (registers[CBR] != 0);
          return (registers[CBR] != 0);
        case 0xD:               /* Branch if NOT Condition Register */
        case 0xD:               /* Branch if NOT Condition Register */
          return (registers[CBR] == 0);
          return (registers[CBR] == 0);
        case 0xE:               /* Branch and Link */
        case 0xE:               /* Branch and Link */
        case 0xF:               /* Branch (unconditional) */
        case 0xF:               /* Branch (unconditional) */
          return 1;
          return 1;
        default:                /* oops? */
        default:                /* oops? */
          return 0;
          return 0;
        }
        }
    case 5:                     /* BNE, BEQ */
    case 5:                     /* BNE, BEQ */
      switch (instr[1] & 0xF0)
      switch (instr[1] & 0xF0)
        {
        {
        case 0x00:              /* Branch if r1 equal to r2 */
        case 0x00:              /* Branch if r1 equal to r2 */
          return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
          return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
        case 0x10:              /* Branch if r1 NOT equal to r2 */
        case 0x10:              /* Branch if r1 NOT equal to r2 */
          return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
          return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
        default:                /* oops? */
        default:                /* oops? */
          return 0;
          return 0;
        }
        }
    case 6:                     /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
    case 6:                     /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
      switch (instr[1] & 0xF0)
      switch (instr[1] & 0xF0)
        {
        {
        case 0x80:              /* Branch if reg equal to zero */
        case 0x80:              /* Branch if reg equal to zero */
          return (registers[instr[1] & 0x0F] == 0);
          return (registers[instr[1] & 0x0F] == 0);
        case 0x90:              /* Branch if reg NOT equal to zero */
        case 0x90:              /* Branch if reg NOT equal to zero */
          return (registers[instr[1] & 0x0F] != 0);
          return (registers[instr[1] & 0x0F] != 0);
        case 0xA0:              /* Branch if reg less than zero */
        case 0xA0:              /* Branch if reg less than zero */
          return (registers[instr[1] & 0x0F] < 0);
          return (registers[instr[1] & 0x0F] < 0);
        case 0xB0:              /* Branch if reg greater or equal to zero */
        case 0xB0:              /* Branch if reg greater or equal to zero */
          return (registers[instr[1] & 0x0F] >= 0);
          return (registers[instr[1] & 0x0F] >= 0);
        case 0xC0:              /* Branch if reg less than or equal to zero */
        case 0xC0:              /* Branch if reg less than or equal to zero */
          return (registers[instr[1] & 0x0F] <= 0);
          return (registers[instr[1] & 0x0F] <= 0);
        case 0xD0:              /* Branch if reg greater than zero */
        case 0xD0:              /* Branch if reg greater than zero */
          return (registers[instr[1] & 0x0F] > 0);
          return (registers[instr[1] & 0x0F] > 0);
        default:                /* oops? */
        default:                /* oops? */
          return 0;
          return 0;
        }
        }
    default:                    /* oops? */
    default:                    /* oops? */
      return 0;
      return 0;
    }
    }
}
}
 
 
static int
static int
branchDestination(instr, branchCode)
branchDestination(instr, branchCode)
     unsigned char *instr;
     unsigned char *instr;
{
{
  switch (branchCode) {
  switch (branchCode) {
  default:
  default:
  case 0:                                        /* not a branch */
  case 0:                                        /* not a branch */
    return 0;
    return 0;
  case 1:                                       /* RTE */
  case 1:                                       /* RTE */
    return registers[BPC] & ~3;                 /* pop BPC into PC */
    return registers[BPC] & ~3;                 /* pop BPC into PC */
  case 2:                                       /* JL or JMP */
  case 2:                                       /* JL or JMP */
    return registers[instr[1] & 0x0F] & ~3;     /* jump thru a register */
    return registers[instr[1] & 0x0F] & ~3;     /* jump thru a register */
  case 3:               /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
  case 3:               /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
    return (((int) instr) & ~3) + ((char) instr[1] << 2);
    return (((int) instr) & ~3) + ((char) instr[1] << 2);
  case 4:               /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
  case 4:               /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
    return ((int) instr +
    return ((int) instr +
            ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2));
            ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2));
  case 5:               /* BNE, BEQ (16-bit relative offset) */
  case 5:               /* BNE, BEQ (16-bit relative offset) */
  case 6:               /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
  case 6:               /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
    return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2));
    return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2));
  }
  }
 
 
  /* An explanatory note: in the last three return expressions, I have
  /* An explanatory note: in the last three return expressions, I have
     cast the most-significant byte of the return offset to char.
     cast the most-significant byte of the return offset to char.
     What this accomplishes is sign extension.  If the other
     What this accomplishes is sign extension.  If the other
     less-significant bytes were signed as well, they would get sign
     less-significant bytes were signed as well, they would get sign
     extended too and, if negative, their leading bits would clobber
     extended too and, if negative, their leading bits would clobber
     the bits of the more-significant bytes ahead of them.  There are
     the bits of the more-significant bytes ahead of them.  There are
     other ways I could have done this, but sign extension from
     other ways I could have done this, but sign extension from
     odd-sized integers is always a pain. */
     odd-sized integers is always a pain. */
}
}
 
 
static void
static void
branchSideEffects(instr, branchCode)
branchSideEffects(instr, branchCode)
     unsigned char *instr;
     unsigned char *instr;
     int branchCode;
     int branchCode;
{
{
  switch (branchCode)
  switch (branchCode)
    {
    {
    case 1:                     /* RTE */
    case 1:                     /* RTE */
      return;                   /* I <THINK> this is already handled... */
      return;                   /* I <THINK> this is already handled... */
    case 2:                     /* JL (or JMP) */
    case 2:                     /* JL (or JMP) */
    case 3:                     /* BL (or BC, BNC, BRA) */
    case 3:                     /* BL (or BC, BNC, BRA) */
    case 4:
    case 4:
      if ((instr[0] & 0x0F) == 0x0E)             /* branch/jump and link */
      if ((instr[0] & 0x0F) == 0x0E)             /* branch/jump and link */
        registers[R14] = (registers[PC] & ~3) + 4;
        registers[R14] = (registers[PC] & ~3) + 4;
      return;
      return;
    default:                    /* any other branch has no side effects */
    default:                    /* any other branch has no side effects */
      return;
      return;
    }
    }
}
}
 
 
static struct STEPPING_CONTEXT {
static struct STEPPING_CONTEXT {
  int stepping;                 /* true when we've started a single-step */
  int stepping;                 /* true when we've started a single-step */
  unsigned long  target_addr;   /* the instr we're trying to execute */
  unsigned long  target_addr;   /* the instr we're trying to execute */
  unsigned long  target_size;   /* the size of the target instr */
  unsigned long  target_size;   /* the size of the target instr */
  unsigned long  noop_addr;     /* where we've inserted a no-op, if any */
  unsigned long  noop_addr;     /* where we've inserted a no-op, if any */
  unsigned long  trap1_addr;    /* the trap following the target instr */
  unsigned long  trap1_addr;    /* the trap following the target instr */
  unsigned long  trap2_addr;    /* the trap at a branch destination, if any */
  unsigned long  trap2_addr;    /* the trap at a branch destination, if any */
  unsigned short noop_save;     /* instruction overwritten by our no-op */
  unsigned short noop_save;     /* instruction overwritten by our no-op */
  unsigned short trap1_save;    /* instruction overwritten by trap1 */
  unsigned short trap1_save;    /* instruction overwritten by trap1 */
  unsigned short trap2_save;    /* instruction overwritten by trap2 */
  unsigned short trap2_save;    /* instruction overwritten by trap2 */
  unsigned short continue_p;    /* true if NOT returning to gdb after step */
  unsigned short continue_p;    /* true if NOT returning to gdb after step */
} stepping;
} stepping;
 
 
/* Function: prepare_to_step
/* Function: prepare_to_step
   Called from handle_exception to prepare the user program to single-step.
   Called from handle_exception to prepare the user program to single-step.
   Places a trap instruction after the target instruction, with special
   Places a trap instruction after the target instruction, with special
   extra handling for branch instructions and for instructions in the
   extra handling for branch instructions and for instructions in the
   second half-word of a word.
   second half-word of a word.
 
 
   Returns: True  if we should actually execute the instruction;
   Returns: True  if we should actually execute the instruction;
            False if we are going to emulate executing the instruction,
            False if we are going to emulate executing the instruction,
            in which case we simply report to GDB that the instruction
            in which case we simply report to GDB that the instruction
            has already been executed.  */
            has already been executed.  */
 
 
#define TRAP1  0x10f1;  /* trap #1 instruction */
#define TRAP1  0x10f1;  /* trap #1 instruction */
#define NOOP   0x7000;  /* noop    instruction */
#define NOOP   0x7000;  /* noop    instruction */
 
 
static unsigned short trap1 = TRAP1;
static unsigned short trap1 = TRAP1;
static unsigned short noop  = NOOP;
static unsigned short noop  = NOOP;
 
 
static int
static int
prepare_to_step(continue_p)
prepare_to_step(continue_p)
     int continue_p;    /* if this isn't REALLY a single-step (see below) */
     int continue_p;    /* if this isn't REALLY a single-step (see below) */
{
{
  unsigned long pc = registers[PC];
  unsigned long pc = registers[PC];
  int branchCode   = isBranch((unsigned char *) pc);
  int branchCode   = isBranch((unsigned char *) pc);
  unsigned char *p;
  unsigned char *p;
 
 
  /* zero out the stepping context
  /* zero out the stepping context
     (paranoia -- it should already be zeroed) */
     (paranoia -- it should already be zeroed) */
  for (p = (unsigned char *) &stepping;
  for (p = (unsigned char *) &stepping;
       p < ((unsigned char *) &stepping) + sizeof(stepping);
       p < ((unsigned char *) &stepping) + sizeof(stepping);
       p++)
       p++)
    *p = 0;
    *p = 0;
 
 
  if (branchCode != 0)                   /* next instruction is a branch */
  if (branchCode != 0)                   /* next instruction is a branch */
    {
    {
      branchSideEffects((unsigned char *) pc, branchCode);
      branchSideEffects((unsigned char *) pc, branchCode);
      if (willBranch((unsigned char *)pc, branchCode))
      if (willBranch((unsigned char *)pc, branchCode))
        registers[PC] = branchDestination((unsigned char *) pc, branchCode);
        registers[PC] = branchDestination((unsigned char *) pc, branchCode);
      else
      else
        registers[PC] = pc + INSTRUCTION_SIZE(pc);
        registers[PC] = pc + INSTRUCTION_SIZE(pc);
      return 0;                  /* branch "executed" -- just notify GDB */
      return 0;                  /* branch "executed" -- just notify GDB */
    }
    }
  else if (((int) pc & 2) != 0)          /* "second-slot" instruction */
  else if (((int) pc & 2) != 0)          /* "second-slot" instruction */
    {
    {
      /* insert no-op before pc */
      /* insert no-op before pc */
      stepping.noop_addr  =  pc - 2;
      stepping.noop_addr  =  pc - 2;
      stepping.noop_save  = *(unsigned short *) stepping.noop_addr;
      stepping.noop_save  = *(unsigned short *) stepping.noop_addr;
      *(unsigned short *) stepping.noop_addr  = noop;
      *(unsigned short *) stepping.noop_addr  = noop;
      /* insert trap  after  pc */
      /* insert trap  after  pc */
      stepping.trap1_addr =  pc + 2;
      stepping.trap1_addr =  pc + 2;
      stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
      stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
      *(unsigned short *) stepping.trap1_addr = trap1;
      *(unsigned short *) stepping.trap1_addr = trap1;
    }
    }
  else                                  /* "first-slot" instruction */
  else                                  /* "first-slot" instruction */
    {
    {
      /* insert trap  after  pc */
      /* insert trap  after  pc */
      stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);
      stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);
      stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
      stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
      *(unsigned short *) stepping.trap1_addr = trap1;
      *(unsigned short *) stepping.trap1_addr = trap1;
    }
    }
  /* "continue_p" means that we are actually doing a continue, and not
  /* "continue_p" means that we are actually doing a continue, and not
     being requested to single-step by GDB.  Sometimes we have to do
     being requested to single-step by GDB.  Sometimes we have to do
     one single-step before continuing, because the PC is on a half-word
     one single-step before continuing, because the PC is on a half-word
     boundary.  There's no way to simply resume at such an address.  */
     boundary.  There's no way to simply resume at such an address.  */
  stepping.continue_p = continue_p;
  stepping.continue_p = continue_p;
  stepping.stepping = 1;                /* starting a single-step */
  stepping.stepping = 1;                /* starting a single-step */
  return 1;
  return 1;
}
}
 
 
/* Function: finish_from_step
/* Function: finish_from_step
   Called from handle_exception to finish up when the user program
   Called from handle_exception to finish up when the user program
   returns from a single-step.  Replaces the instructions that had
   returns from a single-step.  Replaces the instructions that had
   been overwritten by traps or no-ops,
   been overwritten by traps or no-ops,
 
 
   Returns: True  if we should notify GDB that the target stopped.
   Returns: True  if we should notify GDB that the target stopped.
            False if we only single-stepped because we had to before we
            False if we only single-stepped because we had to before we
            could continue (ie. we were trying to continue at a
            could continue (ie. we were trying to continue at a
            half-word boundary).  In that case don't notify GDB:
            half-word boundary).  In that case don't notify GDB:
            just "continue continuing".  */
            just "continue continuing".  */
 
 
static int
static int
finish_from_step()
finish_from_step()
{
{
  if (stepping.stepping)        /* anything to do? */
  if (stepping.stepping)        /* anything to do? */
    {
    {
      int continue_p = stepping.continue_p;
      int continue_p = stepping.continue_p;
      unsigned char *p;
      unsigned char *p;
 
 
      if (stepping.noop_addr)   /* replace instr "under" our no-op */
      if (stepping.noop_addr)   /* replace instr "under" our no-op */
        *(unsigned short *) stepping.noop_addr  = stepping.noop_save;
        *(unsigned short *) stepping.noop_addr  = stepping.noop_save;
      if (stepping.trap1_addr)  /* replace instr "under" our trap  */
      if (stepping.trap1_addr)  /* replace instr "under" our trap  */
        *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
        *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
      if (stepping.trap2_addr)  /* ditto our other trap, if any    */
      if (stepping.trap2_addr)  /* ditto our other trap, if any    */
        *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
        *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
 
 
      for (p = (unsigned char *) &stepping;     /* zero out the stepping context */
      for (p = (unsigned char *) &stepping;     /* zero out the stepping context */
           p < ((unsigned char *) &stepping) + sizeof(stepping);
           p < ((unsigned char *) &stepping) + sizeof(stepping);
           p++)
           p++)
        *p = 0;
        *p = 0;
 
 
      return !(continue_p);
      return !(continue_p);
    }
    }
  else  /* we didn't single-step, therefore this must be a legitimate stop */
  else  /* we didn't single-step, therefore this must be a legitimate stop */
    return 1;
    return 1;
}
}
 
 
struct PSWreg {         /* separate out the bit flags in the PSW register */
struct PSWreg {         /* separate out the bit flags in the PSW register */
  int pad1 : 16;
  int pad1 : 16;
  int bsm  : 1;
  int bsm  : 1;
  int bie  : 1;
  int bie  : 1;
  int pad2 : 5;
  int pad2 : 5;
  int bc   : 1;
  int bc   : 1;
  int sm   : 1;
  int sm   : 1;
  int ie   : 1;
  int ie   : 1;
  int pad3 : 5;
  int pad3 : 5;
  int c    : 1;
  int c    : 1;
} *psw;
} *psw;
 
 
/* Upon entry the value for LR to save has been pushed.
/* Upon entry the value for LR to save has been pushed.
   We unpush that so that the value for the stack pointer saved is correct.
   We unpush that so that the value for the stack pointer saved is correct.
   Upon entry, all other registers are assumed to have not been modified
   Upon entry, all other registers are assumed to have not been modified
   since the interrupt/trap occured.  */
   since the interrupt/trap occured.  */
 
 
asm ("
asm ("
stash_registers:
stash_registers:
        push r0
        push r0
        push r1
        push r1
        seth r1, #shigh(registers)
        seth r1, #shigh(registers)
        add3 r1, r1, #low(registers)
        add3 r1, r1, #low(registers)
        pop r0          ; r1
        pop r0          ; r1
        st r0, @(4,r1)
        st r0, @(4,r1)
        pop r0          ; r0
        pop r0          ; r0
        st r0, @r1
        st r0, @r1
        addi r1, #4     ; only add 4 as subsequent saves are `pre inc'
        addi r1, #4     ; only add 4 as subsequent saves are `pre inc'
        st r2, @+r1
        st r2, @+r1
        st r3, @+r1
        st r3, @+r1
        st r4, @+r1
        st r4, @+r1
        st r5, @+r1
        st r5, @+r1
        st r6, @+r1
        st r6, @+r1
        st r7, @+r1
        st r7, @+r1
        st r8, @+r1
        st r8, @+r1
        st r9, @+r1
        st r9, @+r1
        st r10, @+r1
        st r10, @+r1
        st r11, @+r1
        st r11, @+r1
        st r12, @+r1
        st r12, @+r1
        st r13, @+r1    ; fp
        st r13, @+r1    ; fp
        pop r0          ; lr (r14)
        pop r0          ; lr (r14)
        st r0, @+r1
        st r0, @+r1
        st sp, @+r1     ; sp contains right value at this point
        st sp, @+r1     ; sp contains right value at this point
        mvfc r0, cr0
        mvfc r0, cr0
        st r0, @+r1     ; cr0 == PSW
        st r0, @+r1     ; cr0 == PSW
        mvfc r0, cr1
        mvfc r0, cr1
        st r0, @+r1     ; cr1 == CBR
        st r0, @+r1     ; cr1 == CBR
        mvfc r0, cr2
        mvfc r0, cr2
        st r0, @+r1     ; cr2 == SPI
        st r0, @+r1     ; cr2 == SPI
        mvfc r0, cr3
        mvfc r0, cr3
        st r0, @+r1     ; cr3 == SPU
        st r0, @+r1     ; cr3 == SPU
        mvfc r0, cr6
        mvfc r0, cr6
        st r0, @+r1     ; cr6 == BPC
        st r0, @+r1     ; cr6 == BPC
        st r0, @+r1     ; PC  == BPC
        st r0, @+r1     ; PC  == BPC
        mvfaclo r0
        mvfaclo r0
        st r0, @+r1     ; ACCL
        st r0, @+r1     ; ACCL
        mvfachi r0
        mvfachi r0
        st r0, @+r1     ; ACCH
        st r0, @+r1     ; ACCH
        jmp lr");
        jmp lr");
 
 
/* C routine to clean up what stash_registers did.
/* C routine to clean up what stash_registers did.
   It is called after calling stash_registers.
   It is called after calling stash_registers.
   This is separate from stash_registers as we want to do this in C
   This is separate from stash_registers as we want to do this in C
   but doing stash_registers in C isn't straightforward.  */
   but doing stash_registers in C isn't straightforward.  */
 
 
static void
static void
cleanup_stash ()
cleanup_stash ()
{
{
  psw = (struct PSWreg *) &registers[PSW];      /* fields of PSW register */
  psw = (struct PSWreg *) &registers[PSW];      /* fields of PSW register */
  psw->sm = psw->bsm;           /* fix up pre-trap values of psw fields */
  psw->sm = psw->bsm;           /* fix up pre-trap values of psw fields */
  psw->ie = psw->bie;
  psw->ie = psw->bie;
  psw->c  = psw->bc;
  psw->c  = psw->bc;
  registers[CBR] = psw->bc;             /* fix up pre-trap "C" register */
  registers[CBR] = psw->bc;             /* fix up pre-trap "C" register */
 
 
#if 0 /* FIXME: Was in previous version.  Necessary?
#if 0 /* FIXME: Was in previous version.  Necessary?
         (Remember that we use the "rte" insn to return from the
         (Remember that we use the "rte" insn to return from the
         trap/interrupt so the values of bsm, bie, bc are important.  */
         trap/interrupt so the values of bsm, bie, bc are important.  */
  psw->bsm = psw->bie = psw->bc = 0;     /* zero post-trap values */
  psw->bsm = psw->bie = psw->bc = 0;     /* zero post-trap values */
#endif
#endif
 
 
  /* FIXME: Copied from previous version.  This can probably be deleted
  /* FIXME: Copied from previous version.  This can probably be deleted
     since methinks stash_registers has already done this.  */
     since methinks stash_registers has already done this.  */
  registers[PC] = registers[BPC];       /* pre-trap PC */
  registers[PC] = registers[BPC];       /* pre-trap PC */
 
 
  /* FIXME: Copied from previous version.  Necessary?  */
  /* FIXME: Copied from previous version.  Necessary?  */
  if (psw->sm)                  /* copy R15 into (psw->sm ? SPU : SPI) */
  if (psw->sm)                  /* copy R15 into (psw->sm ? SPU : SPI) */
    registers[SPU] = registers[R15];
    registers[SPU] = registers[R15];
  else
  else
    registers[SPI] = registers[R15];
    registers[SPI] = registers[R15];
}
}
 
 
asm ("
asm ("
restore_and_return:
restore_and_return:
        seth r0, #shigh(registers+8)
        seth r0, #shigh(registers+8)
        add3 r0, r0, #low(registers+8)
        add3 r0, r0, #low(registers+8)
        ld r2, @r0+     ; restore r2
        ld r2, @r0+     ; restore r2
        ld r3, @r0+     ; restore r3
        ld r3, @r0+     ; restore r3
        ld r4, @r0+     ; restore r4
        ld r4, @r0+     ; restore r4
        ld r5, @r0+     ; restore r5
        ld r5, @r0+     ; restore r5
        ld r6, @r0+     ; restore r6
        ld r6, @r0+     ; restore r6
        ld r7, @r0+     ; restore r7
        ld r7, @r0+     ; restore r7
        ld r8, @r0+     ; restore r8
        ld r8, @r0+     ; restore r8
        ld r9, @r0+     ; restore r9
        ld r9, @r0+     ; restore r9
        ld r10, @r0+    ; restore r10
        ld r10, @r0+    ; restore r10
        ld r11, @r0+    ; restore r11
        ld r11, @r0+    ; restore r11
        ld r12, @r0+    ; restore r12
        ld r12, @r0+    ; restore r12
        ld r13, @r0+    ; restore r13
        ld r13, @r0+    ; restore r13
        ld r14, @r0+    ; restore r14
        ld r14, @r0+    ; restore r14
        ld r15, @r0+    ; restore r15
        ld r15, @r0+    ; restore r15
        ld r1, @r0+     ; restore cr0 == PSW
        ld r1, @r0+     ; restore cr0 == PSW
        mvtc r1, cr0
        mvtc r1, cr0
        ld r1, @r0+     ; restore cr1 == CBR (no-op, because it's read only)
        ld r1, @r0+     ; restore cr1 == CBR (no-op, because it's read only)
        mvtc r1, cr1
        mvtc r1, cr1
        ld r1, @r0+     ; restore cr2 == SPI
        ld r1, @r0+     ; restore cr2 == SPI
        mvtc r1, cr2
        mvtc r1, cr2
        ld r1, @r0+     ; restore cr3 == SPU
        ld r1, @r0+     ; restore cr3 == SPU
        mvtc r1, cr3
        mvtc r1, cr3
        addi r0, #4     ; skip BPC
        addi r0, #4     ; skip BPC
        ld r1, @r0+     ; restore cr6 (BPC) == PC
        ld r1, @r0+     ; restore cr6 (BPC) == PC
        mvtc r1, cr6
        mvtc r1, cr6
        ld r1, @r0+     ; restore ACCL
        ld r1, @r0+     ; restore ACCL
        mvtaclo r1
        mvtaclo r1
        ld r1, @r0+     ; restore ACCH
        ld r1, @r0+     ; restore ACCH
        mvtachi r1
        mvtachi r1
        seth r0, #shigh(registers)
        seth r0, #shigh(registers)
        add3 r0, r0, #low(registers)
        add3 r0, r0, #low(registers)
        ld r1, @(4,r0)  ; restore r1
        ld r1, @(4,r0)  ; restore r1
        ld r0, @r0      ; restore r0
        ld r0, @r0      ; restore r0
        rte");
        rte");
 
 
/* General trap handler, called after the registers have been stashed.
/* General trap handler, called after the registers have been stashed.
   NUM is the trap/exception number.  */
   NUM is the trap/exception number.  */
 
 
static void
static void
process_exception (num)
process_exception (num)
     int num;
     int num;
{
{
  cleanup_stash ();
  cleanup_stash ();
  asm volatile ("
  asm volatile ("
        seth r1, #shigh(stackPtr)
        seth r1, #shigh(stackPtr)
        add3 r1, r1, #low(stackPtr)
        add3 r1, r1, #low(stackPtr)
        ld r15, @r1             ; setup local stack (protect user stack)
        ld r15, @r1             ; setup local stack (protect user stack)
        mv r0, %0
        mv r0, %0
        bl handle_exception
        bl handle_exception
        bl restore_and_return"
        bl restore_and_return"
                : : "r" (num) : "r0", "r1");
                : : "r" (num) : "r0", "r1");
}
}
 
 
void _catchException0 ();
void _catchException0 ();
 
 
asm ("
asm ("
_catchException0:
_catchException0:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #0
        ldi r0, #0
        bl process_exception");
        bl process_exception");
 
 
void _catchException1 ();
void _catchException1 ();
 
 
asm ("
asm ("
_catchException1:
_catchException1:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        bl cleanup_stash
        bl cleanup_stash
        seth r1, #shigh(stackPtr)
        seth r1, #shigh(stackPtr)
        add3 r1, r1, #low(stackPtr)
        add3 r1, r1, #low(stackPtr)
        ld r15, @r1             ; setup local stack (protect user stack)
        ld r15, @r1             ; setup local stack (protect user stack)
        seth r1, #shigh(registers + 21*4) ; PC
        seth r1, #shigh(registers + 21*4) ; PC
        add3 r1, r1, #low(registers + 21*4)
        add3 r1, r1, #low(registers + 21*4)
        ld r0, @r1
        ld r0, @r1
        addi r0, #-4            ; back up PC for breakpoint trap.
        addi r0, #-4            ; back up PC for breakpoint trap.
        st r0, @r1              ; FIXME: what about bp in right slot?
        st r0, @r1              ; FIXME: what about bp in right slot?
        ldi r0, #1
        ldi r0, #1
        bl handle_exception
        bl handle_exception
        bl restore_and_return");
        bl restore_and_return");
 
 
void _catchException2 ();
void _catchException2 ();
 
 
asm ("
asm ("
_catchException2:
_catchException2:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #2
        ldi r0, #2
        bl process_exception");
        bl process_exception");
 
 
void _catchException3 ();
void _catchException3 ();
 
 
asm ("
asm ("
_catchException3:
_catchException3:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #3
        ldi r0, #3
        bl process_exception");
        bl process_exception");
 
 
void _catchException4 ();
void _catchException4 ();
 
 
asm ("
asm ("
_catchException4:
_catchException4:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #4
        ldi r0, #4
        bl process_exception");
        bl process_exception");
 
 
void _catchException5 ();
void _catchException5 ();
 
 
asm ("
asm ("
_catchException5:
_catchException5:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #5
        ldi r0, #5
        bl process_exception");
        bl process_exception");
 
 
void _catchException6 ();
void _catchException6 ();
 
 
asm ("
asm ("
_catchException6:
_catchException6:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #6
        ldi r0, #6
        bl process_exception");
        bl process_exception");
 
 
void _catchException7 ();
void _catchException7 ();
 
 
asm ("
asm ("
_catchException7:
_catchException7:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #7
        ldi r0, #7
        bl process_exception");
        bl process_exception");
 
 
void _catchException8 ();
void _catchException8 ();
 
 
asm ("
asm ("
_catchException8:
_catchException8:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #8
        ldi r0, #8
        bl process_exception");
        bl process_exception");
 
 
void _catchException9 ();
void _catchException9 ();
 
 
asm ("
asm ("
_catchException9:
_catchException9:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #9
        ldi r0, #9
        bl process_exception");
        bl process_exception");
 
 
void _catchException10 ();
void _catchException10 ();
 
 
asm ("
asm ("
_catchException10:
_catchException10:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #10
        ldi r0, #10
        bl process_exception");
        bl process_exception");
 
 
void _catchException11 ();
void _catchException11 ();
 
 
asm ("
asm ("
_catchException11:
_catchException11:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #11
        ldi r0, #11
        bl process_exception");
        bl process_exception");
 
 
void _catchException12 ();
void _catchException12 ();
 
 
asm ("
asm ("
_catchException12:
_catchException12:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #12
        ldi r0, #12
        bl process_exception");
        bl process_exception");
 
 
void _catchException13 ();
void _catchException13 ();
 
 
asm ("
asm ("
_catchException13:
_catchException13:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #13
        ldi r0, #13
        bl process_exception");
        bl process_exception");
 
 
void _catchException14 ();
void _catchException14 ();
 
 
asm ("
asm ("
_catchException14:
_catchException14:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #14
        ldi r0, #14
        bl process_exception");
        bl process_exception");
 
 
void _catchException15 ();
void _catchException15 ();
 
 
asm ("
asm ("
_catchException15:
_catchException15:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #15
        ldi r0, #15
        bl process_exception");
        bl process_exception");
 
 
void _catchException16 ();
void _catchException16 ();
 
 
asm ("
asm ("
_catchException16:
_catchException16:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #16
        ldi r0, #16
        bl process_exception");
        bl process_exception");
 
 
void _catchException17 ();
void _catchException17 ();
 
 
asm ("
asm ("
_catchException17:
_catchException17:
        push lr
        push lr
        bl stash_registers
        bl stash_registers
        ; Note that at this point the pushed value of `lr' has been popped
        ; Note that at this point the pushed value of `lr' has been popped
        ldi r0, #17
        ldi r0, #17
        bl process_exception");
        bl process_exception");
 
 
 
 
/* this function is used to set up exception handlers for tracing and
/* this function is used to set up exception handlers for tracing and
   breakpoints */
   breakpoints */
void
void
set_debug_traps()
set_debug_traps()
{
{
  /*  extern void remcomHandler(); */
  /*  extern void remcomHandler(); */
  int i;
  int i;
 
 
  for (i = 0; i < 18; i++)               /* keep a copy of old vectors */
  for (i = 0; i < 18; i++)               /* keep a copy of old vectors */
    if (save_vectors[i] == 0)            /* only copy them the first time */
    if (save_vectors[i] == 0)            /* only copy them the first time */
      save_vectors[i] = getExceptionHandler (i);
      save_vectors[i] = getExceptionHandler (i);
 
 
  stackPtr  = &remcomStack[STACKSIZE/sizeof(int) - 1];
  stackPtr  = &remcomStack[STACKSIZE/sizeof(int) - 1];
 
 
  exceptionHandler (0, _catchException0);
  exceptionHandler (0, _catchException0);
  exceptionHandler (1, _catchException1);
  exceptionHandler (1, _catchException1);
  exceptionHandler (2, _catchException2);
  exceptionHandler (2, _catchException2);
  exceptionHandler (3, _catchException3);
  exceptionHandler (3, _catchException3);
  exceptionHandler (4, _catchException4);
  exceptionHandler (4, _catchException4);
  exceptionHandler (5, _catchException5);
  exceptionHandler (5, _catchException5);
  exceptionHandler (6, _catchException6);
  exceptionHandler (6, _catchException6);
  exceptionHandler (7, _catchException7);
  exceptionHandler (7, _catchException7);
  exceptionHandler (8, _catchException8);
  exceptionHandler (8, _catchException8);
  exceptionHandler (9, _catchException9);
  exceptionHandler (9, _catchException9);
  exceptionHandler (10, _catchException10);
  exceptionHandler (10, _catchException10);
  exceptionHandler (11, _catchException11);
  exceptionHandler (11, _catchException11);
  exceptionHandler (12, _catchException12);
  exceptionHandler (12, _catchException12);
  exceptionHandler (13, _catchException13);
  exceptionHandler (13, _catchException13);
  exceptionHandler (14, _catchException14);
  exceptionHandler (14, _catchException14);
  exceptionHandler (15, _catchException15);
  exceptionHandler (15, _catchException15);
  exceptionHandler (16, _catchException16);
  exceptionHandler (16, _catchException16);
  /*  exceptionHandler (17, _catchException17); */
  /*  exceptionHandler (17, _catchException17); */
 
 
  initialized = 1;
  initialized = 1;
}
}
 
 
/* This function will generate a breakpoint exception.  It is used at the
/* This function will generate a breakpoint exception.  It is used at the
   beginning of a program to sync up with a debugger and can be used
   beginning of a program to sync up with a debugger and can be used
   otherwise as a quick means to stop program execution and "break" into
   otherwise as a quick means to stop program execution and "break" into
   the debugger. */
   the debugger. */
 
 
#define BREAKPOINT() asm volatile ("    trap #2");
#define BREAKPOINT() asm volatile ("    trap #2");
 
 
void
void
breakpoint()
breakpoint()
{
{
  if (initialized)
  if (initialized)
    BREAKPOINT();
    BREAKPOINT();
}
}
 
 
/* STDOUT section:
/* STDOUT section:
   Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
   Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
   Functions: gdb_putchar(char ch)
   Functions: gdb_putchar(char ch)
              gdb_puts(char *str)
              gdb_puts(char *str)
              gdb_write(char *str, int len)
              gdb_write(char *str, int len)
              gdb_error(char *format, char *parm)
              gdb_error(char *format, char *parm)
              */
              */
 
 
/* Function: gdb_putchar(int)
/* Function: gdb_putchar(int)
   Make gdb write a char to stdout.
   Make gdb write a char to stdout.
   Returns: the char */
   Returns: the char */
 
 
static int
static int
gdb_putchar(ch)
gdb_putchar(ch)
     int ch;
     int ch;
{
{
  char buf[4];
  char buf[4];
 
 
  buf[0] = 'O';
  buf[0] = 'O';
  buf[1] = hexchars[ch >> 4];
  buf[1] = hexchars[ch >> 4];
  buf[2] = hexchars[ch & 0x0F];
  buf[2] = hexchars[ch & 0x0F];
  buf[3] = 0;
  buf[3] = 0;
  putpacket(buf);
  putpacket(buf);
  return ch;
  return ch;
}
}
 
 
/* Function: gdb_write(char *, int)
/* Function: gdb_write(char *, int)
   Make gdb write n bytes to stdout (not assumed to be null-terminated).
   Make gdb write n bytes to stdout (not assumed to be null-terminated).
   Returns: number of bytes written */
   Returns: number of bytes written */
 
 
static int
static int
gdb_write(data, len)
gdb_write(data, len)
     char *data;
     char *data;
     int len;
     int len;
{
{
  char *buf, *cpy;
  char *buf, *cpy;
  int i;
  int i;
 
 
  buf = remcomOutBuffer;
  buf = remcomOutBuffer;
  buf[0] = 'O';
  buf[0] = 'O';
  i = 0;
  i = 0;
  while (i < len)
  while (i < len)
    {
    {
      for (cpy = buf+1;
      for (cpy = buf+1;
           i < len && cpy < buf + sizeof(remcomOutBuffer) - 3;
           i < len && cpy < buf + sizeof(remcomOutBuffer) - 3;
           i++)
           i++)
        {
        {
          *cpy++ = hexchars[data[i] >> 4];
          *cpy++ = hexchars[data[i] >> 4];
          *cpy++ = hexchars[data[i] & 0x0F];
          *cpy++ = hexchars[data[i] & 0x0F];
        }
        }
      *cpy = 0;
      *cpy = 0;
      putpacket(buf);
      putpacket(buf);
    }
    }
  return len;
  return len;
}
}
 
 
/* Function: gdb_puts(char *)
/* Function: gdb_puts(char *)
   Make gdb write a null-terminated string to stdout.
   Make gdb write a null-terminated string to stdout.
   Returns: the length of the string */
   Returns: the length of the string */
 
 
static int
static int
gdb_puts(str)
gdb_puts(str)
     char *str;
     char *str;
{
{
  return gdb_write(str, strlen(str));
  return gdb_write(str, strlen(str));
}
}
 
 
/* Function: gdb_error(char *, char *)
/* Function: gdb_error(char *, char *)
   Send an error message to gdb's stdout.
   Send an error message to gdb's stdout.
   First string may have 1 (one) optional "%s" in it, which
   First string may have 1 (one) optional "%s" in it, which
   will cause the optional second string to be inserted.  */
   will cause the optional second string to be inserted.  */
 
 
static void
static void
gdb_error(format, parm)
gdb_error(format, parm)
     char * format;
     char * format;
     char * parm;
     char * parm;
{
{
  char buf[400], *cpy;
  char buf[400], *cpy;
  int len;
  int len;
 
 
  if (remote_debug)
  if (remote_debug)
    {
    {
      if (format && *format)
      if (format && *format)
        len = strlen(format);
        len = strlen(format);
      else
      else
        return;             /* empty input */
        return;             /* empty input */
 
 
      if (parm && *parm)
      if (parm && *parm)
        len += strlen(parm);
        len += strlen(parm);
 
 
      for (cpy = buf; *format; )
      for (cpy = buf; *format; )
        {
        {
          if (format[0] == '%' && format[1] == 's') /* include second string */
          if (format[0] == '%' && format[1] == 's') /* include second string */
            {
            {
              format += 2;          /* advance two chars instead of just one */
              format += 2;          /* advance two chars instead of just one */
              while (parm && *parm)
              while (parm && *parm)
                *cpy++ = *parm++;
                *cpy++ = *parm++;
            }
            }
          else
          else
            *cpy++ = *format++;
            *cpy++ = *format++;
        }
        }
      *cpy = '\0';
      *cpy = '\0';
      gdb_puts(buf);
      gdb_puts(buf);
    }
    }
}
}
 
 
static unsigned char *
static unsigned char *
strcpy (unsigned char *dest, const unsigned char *src)
strcpy (unsigned char *dest, const unsigned char *src)
{
{
  unsigned char *ret = dest;
  unsigned char *ret = dest;
 
 
  if (dest && src)
  if (dest && src)
    {
    {
      while (*src)
      while (*src)
        *dest++ = *src++;
        *dest++ = *src++;
      *dest = 0;
      *dest = 0;
    }
    }
  return ret;
  return ret;
}
}
 
 
static int
static int
strlen (const unsigned char *src)
strlen (const unsigned char *src)
{
{
  int ret;
  int ret;
 
 
  for (ret = 0; *src; src++)
  for (ret = 0; *src; src++)
    ret++;
    ret++;
 
 
  return ret;
  return ret;
}
}
 
 
#if 0
#if 0
void exit (code)
void exit (code)
     int code;
     int code;
{
{
  _exit (code);
  _exit (code);
}
}
 
 
int atexit (void *p)
int atexit (void *p)
{
{
  return 0;
  return 0;
}
}
 
 
void abort (void)
void abort (void)
{
{
  _exit (1);
  _exit (1);
}
}
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.