Home | History | Annotate | Line # | Download | only in stubs
      1  1.1  christos /****************************************************************************
      2  1.1  christos 
      3  1.1  christos 		THIS SOFTWARE IS NOT COPYRIGHTED
      4  1.1  christos 
      5  1.1  christos    HP offers the following for use in the public domain.  HP makes no
      6  1.1  christos    warranty with regard to the software or it's performance and the
      7  1.1  christos    user accepts the software "AS IS" with all faults.
      8  1.1  christos 
      9  1.1  christos    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
     10  1.1  christos    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     11  1.1  christos    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     12  1.1  christos 
     13  1.1  christos ****************************************************************************/
     14  1.1  christos 
     15  1.1  christos /****************************************************************************
     16  1.1  christos  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
     17  1.1  christos  *
     18  1.1  christos  *  Module name: remcom.c $
     19  1.1  christos  *  Revision: 1.34 $
     20  1.1  christos  *  Date: 91/03/09 12:29:49 $
     21  1.1  christos  *  Contributor:     Lake Stevens Instrument Division$
     22  1.1  christos  *
     23  1.1  christos  *  Description:     low level support for gdb debugger. $
     24  1.1  christos  *
     25  1.1  christos  *  Considerations:  only works on target hardware $
     26  1.1  christos  *
     27  1.1  christos  *  Written by:      Glenn Engel $
     28  1.1  christos  *  ModuleState:     Experimental $
     29  1.1  christos  *
     30  1.1  christos  *  NOTES:           See Below $
     31  1.1  christos  *
     32  1.1  christos  *  Modified for M32R by Michael Snyder, Cygnus Support.
     33  1.1  christos  *
     34  1.1  christos  *  To enable debugger support, two things need to happen.  One, a
     35  1.1  christos  *  call to set_debug_traps() is necessary in order to allow any breakpoints
     36  1.1  christos  *  or error conditions to be properly intercepted and reported to gdb.
     37  1.1  christos  *  Two, a breakpoint needs to be generated to begin communication.  This
     38  1.1  christos  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
     39  1.1  christos  *  simulates a breakpoint by executing a trap #1.
     40  1.1  christos  *
     41  1.1  christos  *  The external function exceptionHandler() is
     42  1.1  christos  *  used to attach a specific handler to a specific M32R vector number.
     43  1.1  christos  *  It should use the same privilege level it runs at.  It should
     44  1.1  christos  *  install it as an interrupt gate so that interrupts are masked
     45  1.1  christos  *  while the handler runs.
     46  1.1  christos  *
     47  1.1  christos  *  Because gdb will sometimes write to the stack area to execute function
     48  1.1  christos  *  calls, this program cannot rely on using the supervisor stack so it
     49  1.8  christos  *  uses its own stack area reserved in the int array remcomStack.
     50  1.1  christos  *
     51  1.1  christos  *************
     52  1.1  christos  *
     53  1.1  christos  *    The following gdb commands are supported:
     54  1.1  christos  *
     55  1.1  christos  * command          function                               Return value
     56  1.1  christos  *
     57  1.1  christos  *    g             return the value of the CPU registers  hex data or ENN
     58  1.1  christos  *    G             set the value of the CPU registers     OK or ENN
     59  1.1  christos  *
     60  1.1  christos  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
     61  1.1  christos  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
     62  1.1  christos  *    XAA..AA,LLLL: Write LLLL binary bytes at address     OK or ENN
     63  1.1  christos  *                  AA..AA
     64  1.1  christos  *
     65  1.1  christos  *    c             Resume at current address              SNN   ( signal NN)
     66  1.1  christos  *    cAA..AA       Continue at address AA..AA             SNN
     67  1.1  christos  *
     68  1.1  christos  *    s             Step one instruction                   SNN
     69  1.1  christos  *    sAA..AA       Step one instruction from AA..AA       SNN
     70  1.1  christos  *
     71  1.1  christos  *    k             kill
     72  1.1  christos  *
     73  1.1  christos  *    ?             What was the last sigval ?             SNN   (signal NN)
     74  1.1  christos  *
     75  1.1  christos  * All commands and responses are sent with a packet which includes a
     76  1.1  christos  * checksum.  A packet consists of
     77  1.1  christos  *
     78  1.1  christos  * $<packet info>#<checksum>.
     79  1.1  christos  *
     80  1.1  christos  * where
     81  1.1  christos  * <packet info> :: <characters representing the command or response>
     82  1.1  christos  * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
     83  1.1  christos  *
     84  1.1  christos  * When a packet is received, it is first acknowledged with either '+' or '-'.
     85  1.1  christos  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
     86  1.1  christos  *
     87  1.1  christos  * Example:
     88  1.1  christos  *
     89  1.1  christos  * Host:                  Reply:
     90  1.1  christos  * $m0,10#2a               +$00010203040506070809101112131415#42
     91  1.1  christos  *
     92  1.1  christos  ****************************************************************************/
     93  1.1  christos 
     94  1.1  christos 
     95  1.1  christos /************************************************************************
     96  1.1  christos  *
     97  1.1  christos  * external low-level support routines
     98  1.1  christos  */
     99  1.1  christos extern void putDebugChar ();	/* write a single character      */
    100  1.1  christos extern int getDebugChar ();	/* read and return a single char */
    101  1.1  christos extern void exceptionHandler ();	/* assign an exception handler   */
    102  1.1  christos 
    103  1.1  christos /*****************************************************************************
    104  1.1  christos  * BUFMAX defines the maximum number of characters in inbound/outbound buffers
    105  1.1  christos  * at least NUMREGBYTES*2 are needed for register packets
    106  1.1  christos  */
    107  1.1  christos #define BUFMAX 400
    108  1.1  christos 
    109  1.1  christos static char initialized;	/* boolean flag. != 0 means we've been initialized */
    110  1.1  christos 
    111  1.1  christos int remote_debug;
    112  1.1  christos /*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
    113  1.1  christos 
    114  1.1  christos static const unsigned char hexchars[] = "0123456789abcdef";
    115  1.1  christos 
    116  1.1  christos #define NUMREGS 24
    117  1.1  christos 
    118  1.1  christos /* Number of bytes of registers.  */
    119  1.1  christos #define NUMREGBYTES (NUMREGS * 4)
    120  1.1  christos enum regnames
    121  1.1  christos { R0, R1, R2, R3, R4, R5, R6, R7,
    122  1.1  christos   R8, R9, R10, R11, R12, R13, R14, R15,
    123  1.1  christos   PSW, CBR, SPI, SPU, BPC, PC, ACCL, ACCH
    124  1.1  christos };
    125  1.1  christos 
    126  1.1  christos enum SYS_calls
    127  1.1  christos {
    128  1.1  christos   SYS_null,
    129  1.1  christos   SYS_exit,
    130  1.1  christos   SYS_open,
    131  1.1  christos   SYS_close,
    132  1.1  christos   SYS_read,
    133  1.1  christos   SYS_write,
    134  1.1  christos   SYS_lseek,
    135  1.1  christos   SYS_unlink,
    136  1.1  christos   SYS_getpid,
    137  1.1  christos   SYS_kill,
    138  1.1  christos   SYS_fstat,
    139  1.1  christos   SYS_sbrk,
    140  1.1  christos   SYS_fork,
    141  1.1  christos   SYS_execve,
    142  1.1  christos   SYS_wait4,
    143  1.1  christos   SYS_link,
    144  1.1  christos   SYS_chdir,
    145  1.1  christos   SYS_stat,
    146  1.1  christos   SYS_utime,
    147  1.1  christos   SYS_chown,
    148  1.1  christos   SYS_chmod,
    149  1.1  christos   SYS_time,
    150  1.1  christos   SYS_pipe
    151  1.1  christos };
    152  1.1  christos 
    153  1.1  christos static int registers[NUMREGS];
    154  1.1  christos 
    155  1.1  christos #define STACKSIZE 8096
    156  1.1  christos static unsigned char remcomInBuffer[BUFMAX];
    157  1.1  christos static unsigned char remcomOutBuffer[BUFMAX];
    158  1.1  christos static int remcomStack[STACKSIZE / sizeof (int)];
    159  1.1  christos static int *stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
    160  1.1  christos 
    161  1.1  christos static unsigned int save_vectors[18];	/* previous exception vectors */
    162  1.1  christos 
    163  1.1  christos /* Indicate to caller of mem2hex or hex2mem that there has been an error. */
    164  1.1  christos static volatile int mem_err = 0;
    165  1.1  christos 
    166  1.1  christos /* Store the vector number here (since GDB only gets the signal
    167  1.1  christos    number through the usual means, and that's not very specific).  */
    168  1.1  christos int gdb_m32r_vector = -1;
    169  1.1  christos 
    170  1.1  christos #if 0
    171  1.8  christos #include "syscall.h"
    172  1.1  christos #endif
    173  1.1  christos 
    174  1.1  christos /* Global entry points:
    175  1.1  christos  */
    176  1.1  christos 
    177  1.1  christos extern void handle_exception (int);
    178  1.1  christos extern void set_debug_traps (void);
    179  1.1  christos extern void breakpoint (void);
    180  1.1  christos 
    181  1.1  christos /* Local functions:
    182  1.1  christos  */
    183  1.1  christos 
    184  1.1  christos static int computeSignal (int);
    185  1.1  christos static void putpacket (unsigned char *);
    186  1.1  christos static unsigned char *getpacket (void);
    187  1.1  christos 
    188  1.1  christos static unsigned char *mem2hex (unsigned char *, unsigned char *, int, int);
    189  1.1  christos static unsigned char *hex2mem (unsigned char *, unsigned char *, int, int);
    190  1.1  christos static int hexToInt (unsigned char **, int *);
    191  1.1  christos static unsigned char *bin2mem (unsigned char *, unsigned char *, int, int);
    192  1.1  christos static void stash_registers (void);
    193  1.1  christos static void restore_registers (void);
    194  1.1  christos static int prepare_to_step (int);
    195  1.1  christos static int finish_from_step (void);
    196  1.1  christos static unsigned long crc32 (unsigned char *, int, unsigned long);
    197  1.1  christos 
    198  1.1  christos static void gdb_error (char *, char *);
    199  1.1  christos static int gdb_putchar (int), gdb_puts (char *), gdb_write (char *, int);
    200  1.1  christos 
    201  1.1  christos static unsigned char *strcpy (unsigned char *, const unsigned char *);
    202  1.1  christos static int strlen (const unsigned char *);
    203  1.1  christos 
    204  1.1  christos /*
    205  1.1  christos  * This function does all command procesing for interfacing to gdb.
    206  1.1  christos  */
    207  1.1  christos 
    208  1.1  christos void
    209  1.1  christos handle_exception (int exceptionVector)
    210  1.1  christos {
    211  1.1  christos   int sigval, stepping;
    212  1.1  christos   int addr, length, i;
    213  1.1  christos   unsigned char *ptr;
    214  1.1  christos   unsigned char buf[16];
    215  1.1  christos   int binary;
    216  1.1  christos 
    217  1.1  christos   if (!finish_from_step ())
    218  1.1  christos     return;			/* "false step": let the target continue */
    219  1.1  christos 
    220  1.1  christos   gdb_m32r_vector = exceptionVector;
    221  1.1  christos 
    222  1.1  christos   if (remote_debug)
    223  1.1  christos     {
    224  1.1  christos       mem2hex ((unsigned char *) &exceptionVector, buf, 4, 0);
    225  1.1  christos       gdb_error ("Handle exception %s, ", buf);
    226  1.1  christos       mem2hex ((unsigned char *) &registers[PC], buf, 4, 0);
    227  1.1  christos       gdb_error ("PC == 0x%s\n", buf);
    228  1.1  christos     }
    229  1.1  christos 
    230  1.1  christos   /* reply to host that an exception has occurred */
    231  1.1  christos   sigval = computeSignal (exceptionVector);
    232  1.1  christos 
    233  1.1  christos   ptr = remcomOutBuffer;
    234  1.1  christos 
    235  1.1  christos   *ptr++ = 'T';			/* notify gdb with signo, PC, FP and SP */
    236  1.1  christos   *ptr++ = hexchars[sigval >> 4];
    237  1.1  christos   *ptr++ = hexchars[sigval & 0xf];
    238  1.1  christos 
    239  1.1  christos   *ptr++ = hexchars[PC >> 4];
    240  1.1  christos   *ptr++ = hexchars[PC & 0xf];
    241  1.1  christos   *ptr++ = ':';
    242  1.1  christos   ptr = mem2hex ((unsigned char *) &registers[PC], ptr, 4, 0);	/* PC */
    243  1.1  christos   *ptr++ = ';';
    244  1.1  christos 
    245  1.1  christos   *ptr++ = hexchars[R13 >> 4];
    246  1.1  christos   *ptr++ = hexchars[R13 & 0xf];
    247  1.1  christos   *ptr++ = ':';
    248  1.1  christos   ptr = mem2hex ((unsigned char *) &registers[R13], ptr, 4, 0);	/* FP */
    249  1.1  christos   *ptr++ = ';';
    250  1.1  christos 
    251  1.1  christos   *ptr++ = hexchars[R15 >> 4];
    252  1.1  christos   *ptr++ = hexchars[R15 & 0xf];
    253  1.1  christos   *ptr++ = ':';
    254  1.1  christos   ptr = mem2hex ((unsigned char *) &registers[R15], ptr, 4, 0);	/* SP */
    255  1.1  christos   *ptr++ = ';';
    256  1.1  christos   *ptr++ = 0;
    257  1.1  christos 
    258  1.1  christos   if (exceptionVector == 0)	/* simulated SYS call stuff */
    259  1.1  christos     {
    260  1.1  christos       mem2hex ((unsigned char *) &registers[PC], buf, 4, 0);
    261  1.1  christos       switch (registers[R0])
    262  1.1  christos 	{
    263  1.1  christos 	case SYS_exit:
    264  1.1  christos 	  gdb_error ("Target program has exited at %s\n", buf);
    265  1.1  christos 	  ptr = remcomOutBuffer;
    266  1.1  christos 	  *ptr++ = 'W';
    267  1.1  christos 	  sigval = registers[R1] & 0xff;
    268  1.1  christos 	  *ptr++ = hexchars[sigval >> 4];
    269  1.1  christos 	  *ptr++ = hexchars[sigval & 0xf];
    270  1.1  christos 	  *ptr++ = 0;
    271  1.1  christos 	  break;
    272  1.1  christos 	case SYS_open:
    273  1.1  christos 	  gdb_error ("Target attempts SYS_open call at %s\n", buf);
    274  1.1  christos 	  break;
    275  1.1  christos 	case SYS_close:
    276  1.1  christos 	  gdb_error ("Target attempts SYS_close call at %s\n", buf);
    277  1.1  christos 	  break;
    278  1.1  christos 	case SYS_read:
    279  1.1  christos 	  gdb_error ("Target attempts SYS_read call at %s\n", buf);
    280  1.1  christos 	  break;
    281  1.1  christos 	case SYS_write:
    282  1.1  christos 	  if (registers[R1] == 1 ||	/* write to stdout  */
    283  1.1  christos 	      registers[R1] == 2)	/* write to stderr  */
    284  1.1  christos 	    {			/* (we can do that) */
    285  1.1  christos 	      registers[R0] =
    286  1.1  christos 		gdb_write ((void *) registers[R2], registers[R3]);
    287  1.1  christos 	      return;
    288  1.1  christos 	    }
    289  1.1  christos 	  else
    290  1.1  christos 	    gdb_error ("Target attempts SYS_write call at %s\n", buf);
    291  1.1  christos 	  break;
    292  1.1  christos 	case SYS_lseek:
    293  1.1  christos 	  gdb_error ("Target attempts SYS_lseek call at %s\n", buf);
    294  1.1  christos 	  break;
    295  1.1  christos 	case SYS_unlink:
    296  1.1  christos 	  gdb_error ("Target attempts SYS_unlink call at %s\n", buf);
    297  1.1  christos 	  break;
    298  1.1  christos 	case SYS_getpid:
    299  1.1  christos 	  gdb_error ("Target attempts SYS_getpid call at %s\n", buf);
    300  1.1  christos 	  break;
    301  1.1  christos 	case SYS_kill:
    302  1.1  christos 	  gdb_error ("Target attempts SYS_kill call at %s\n", buf);
    303  1.1  christos 	  break;
    304  1.1  christos 	case SYS_fstat:
    305  1.1  christos 	  gdb_error ("Target attempts SYS_fstat call at %s\n", buf);
    306  1.1  christos 	  break;
    307  1.1  christos 	default:
    308  1.1  christos 	  gdb_error ("Target attempts unknown SYS call at %s\n", buf);
    309  1.1  christos 	  break;
    310  1.1  christos 	}
    311  1.1  christos     }
    312  1.1  christos 
    313  1.1  christos   putpacket (remcomOutBuffer);
    314  1.1  christos 
    315  1.1  christos   stepping = 0;
    316  1.1  christos 
    317  1.1  christos   while (1 == 1)
    318  1.1  christos     {
    319  1.1  christos       remcomOutBuffer[0] = 0;
    320  1.1  christos       ptr = getpacket ();
    321  1.1  christos       binary = 0;
    322  1.1  christos       switch (*ptr++)
    323  1.1  christos 	{
    324  1.1  christos 	default:		/* Unknown code.  Return an empty reply message. */
    325  1.1  christos 	  break;
    326  1.1  christos 	case 'R':
    327  1.1  christos 	  if (hexToInt (&ptr, &addr))
    328  1.1  christos 	    registers[PC] = addr;
    329  1.1  christos 	  strcpy (remcomOutBuffer, "OK");
    330  1.1  christos 	  break;
    331  1.1  christos 	case '!':
    332  1.1  christos 	  strcpy (remcomOutBuffer, "OK");
    333  1.1  christos 	  break;
    334  1.1  christos 	case 'X':		/* XAA..AA,LLLL:<binary data>#cs */
    335  1.1  christos 	  binary = 1;
    336  1.1  christos 	case 'M':		/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
    337  1.1  christos 	  /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
    338  1.1  christos 	  {
    339  1.1  christos 	    if (hexToInt (&ptr, &addr))
    340  1.1  christos 	      if (*(ptr++) == ',')
    341  1.1  christos 		if (hexToInt (&ptr, &length))
    342  1.1  christos 		  if (*(ptr++) == ':')
    343  1.1  christos 		    {
    344  1.1  christos 		      mem_err = 0;
    345  1.1  christos 		      if (binary)
    346  1.1  christos 			bin2mem (ptr, (unsigned char *) addr, length, 1);
    347  1.1  christos 		      else
    348  1.1  christos 			hex2mem (ptr, (unsigned char *) addr, length, 1);
    349  1.1  christos 		      if (mem_err)
    350  1.1  christos 			{
    351  1.1  christos 			  strcpy (remcomOutBuffer, "E03");
    352  1.1  christos 			  gdb_error ("memory fault", "");
    353  1.1  christos 			}
    354  1.1  christos 		      else
    355  1.1  christos 			{
    356  1.1  christos 			  strcpy (remcomOutBuffer, "OK");
    357  1.1  christos 			}
    358  1.1  christos 		      ptr = 0;
    359  1.1  christos 		    }
    360  1.1  christos 	    if (ptr)
    361  1.1  christos 	      {
    362  1.1  christos 		strcpy (remcomOutBuffer, "E02");
    363  1.1  christos 	      }
    364  1.1  christos 	  }
    365  1.1  christos 	  break;
    366  1.1  christos 	case 'm':		/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
    367  1.1  christos 	  /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
    368  1.1  christos 	  if (hexToInt (&ptr, &addr))
    369  1.1  christos 	    if (*(ptr++) == ',')
    370  1.1  christos 	      if (hexToInt (&ptr, &length))
    371  1.1  christos 		{
    372  1.1  christos 		  ptr = 0;
    373  1.1  christos 		  mem_err = 0;
    374  1.1  christos 		  mem2hex ((unsigned char *) addr, remcomOutBuffer, length,
    375  1.1  christos 			   1);
    376  1.1  christos 		  if (mem_err)
    377  1.1  christos 		    {
    378  1.1  christos 		      strcpy (remcomOutBuffer, "E03");
    379  1.1  christos 		      gdb_error ("memory fault", "");
    380  1.1  christos 		    }
    381  1.1  christos 		}
    382  1.1  christos 	  if (ptr)
    383  1.1  christos 	    {
    384  1.1  christos 	      strcpy (remcomOutBuffer, "E01");
    385  1.1  christos 	    }
    386  1.1  christos 	  break;
    387  1.1  christos 	case '?':
    388  1.1  christos 	  remcomOutBuffer[0] = 'S';
    389  1.1  christos 	  remcomOutBuffer[1] = hexchars[sigval >> 4];
    390  1.1  christos 	  remcomOutBuffer[2] = hexchars[sigval % 16];
    391  1.1  christos 	  remcomOutBuffer[3] = 0;
    392  1.1  christos 	  break;
    393  1.1  christos 	case 'd':
    394  1.1  christos 	  remote_debug = !(remote_debug);	/* toggle debug flag */
    395  1.1  christos 	  break;
    396  1.1  christos 	case 'g':		/* return the value of the CPU registers */
    397  1.1  christos 	  mem2hex ((unsigned char *) registers, remcomOutBuffer, NUMREGBYTES,
    398  1.1  christos 		   0);
    399  1.1  christos 	  break;
    400  1.1  christos 	case 'P':		/* set the value of a single CPU register - return OK */
    401  1.1  christos 	  {
    402  1.1  christos 	    int regno;
    403  1.1  christos 
    404  1.1  christos 	    if (hexToInt (&ptr, &regno) && *ptr++ == '=')
    405  1.1  christos 	      if (regno >= 0 && regno < NUMREGS)
    406  1.1  christos 		{
    407  1.1  christos 		  int stackmode;
    408  1.1  christos 
    409  1.1  christos 		  hex2mem (ptr, (unsigned char *) &registers[regno], 4, 0);
    410  1.1  christos 		  /*
    411  1.1  christos 		   * Since we just changed a single CPU register, let's
    412  1.1  christos 		   * make sure to keep the several stack pointers consistant.
    413  1.1  christos 		   */
    414  1.1  christos 		  stackmode = registers[PSW] & 0x80;
    415  1.1  christos 		  if (regno == R15)	/* stack pointer changed */
    416  1.1  christos 		    {		/* need to change SPI or SPU */
    417  1.1  christos 		      if (stackmode == 0)
    418  1.1  christos 			registers[SPI] = registers[R15];
    419  1.1  christos 		      else
    420  1.1  christos 			registers[SPU] = registers[R15];
    421  1.1  christos 		    }
    422  1.1  christos 		  else if (regno == SPU)	/* "user" stack pointer changed */
    423  1.1  christos 		    {
    424  1.1  christos 		      if (stackmode != 0)	/* stack in user mode: copy SP */
    425  1.1  christos 			registers[R15] = registers[SPU];
    426  1.1  christos 		    }
    427  1.1  christos 		  else if (regno == SPI)	/* "interrupt" stack pointer changed */
    428  1.1  christos 		    {
    429  1.1  christos 		      if (stackmode == 0)	/* stack in interrupt mode: copy SP */
    430  1.1  christos 			registers[R15] = registers[SPI];
    431  1.1  christos 		    }
    432  1.1  christos 		  else if (regno == PSW)	/* stack mode may have changed! */
    433  1.1  christos 		    {		/* force SP to either SPU or SPI */
    434  1.1  christos 		      if (stackmode == 0)	/* stack in user mode */
    435  1.1  christos 			registers[R15] = registers[SPI];
    436  1.1  christos 		      else	/* stack in interrupt mode */
    437  1.1  christos 			registers[R15] = registers[SPU];
    438  1.1  christos 		    }
    439  1.1  christos 		  strcpy (remcomOutBuffer, "OK");
    440  1.1  christos 		  break;
    441  1.1  christos 		}
    442  1.1  christos 	    strcpy (remcomOutBuffer, "E01");
    443  1.1  christos 	    break;
    444  1.1  christos 	  }
    445  1.1  christos 	case 'G':		/* set the value of the CPU registers - return OK */
    446  1.1  christos 	  hex2mem (ptr, (unsigned char *) registers, NUMREGBYTES, 0);
    447  1.1  christos 	  strcpy (remcomOutBuffer, "OK");
    448  1.1  christos 	  break;
    449  1.1  christos 	case 's':		/* sAA..AA      Step one instruction from AA..AA(optional) */
    450  1.1  christos 	  stepping = 1;
    451  1.1  christos 	case 'c':		/* cAA..AA      Continue from address AA..AA(optional) */
    452  1.1  christos 	  /* try to read optional parameter, pc unchanged if no parm */
    453  1.1  christos 	  if (hexToInt (&ptr, &addr))
    454  1.1  christos 	    registers[PC] = addr;
    455  1.1  christos 
    456  1.1  christos 	  if (stepping)		/* single-stepping */
    457  1.1  christos 	    {
    458  1.1  christos 	      if (!prepare_to_step (0))	/* set up for single-step */
    459  1.1  christos 		{
    460  1.1  christos 		  /* prepare_to_step has already emulated the target insn:
    461  1.1  christos 		     Send SIGTRAP to gdb, don't resume the target at all.  */
    462  1.1  christos 		  ptr = remcomOutBuffer;
    463  1.1  christos 		  *ptr++ = 'T';	/* Simulate stopping with SIGTRAP */
    464  1.1  christos 		  *ptr++ = '0';
    465  1.1  christos 		  *ptr++ = '5';
    466  1.1  christos 
    467  1.1  christos 		  *ptr++ = hexchars[PC >> 4];	/* send PC */
    468  1.1  christos 		  *ptr++ = hexchars[PC & 0xf];
    469  1.1  christos 		  *ptr++ = ':';
    470  1.1  christos 		  ptr = mem2hex ((unsigned char *) &registers[PC], ptr, 4, 0);
    471  1.1  christos 		  *ptr++ = ';';
    472  1.1  christos 
    473  1.1  christos 		  *ptr++ = hexchars[R13 >> 4];	/* send FP */
    474  1.1  christos 		  *ptr++ = hexchars[R13 & 0xf];
    475  1.1  christos 		  *ptr++ = ':';
    476  1.1  christos 		  ptr =
    477  1.1  christos 		    mem2hex ((unsigned char *) &registers[R13], ptr, 4, 0);
    478  1.1  christos 		  *ptr++ = ';';
    479  1.1  christos 
    480  1.1  christos 		  *ptr++ = hexchars[R15 >> 4];	/* send SP */
    481  1.1  christos 		  *ptr++ = hexchars[R15 & 0xf];
    482  1.1  christos 		  *ptr++ = ':';
    483  1.1  christos 		  ptr =
    484  1.1  christos 		    mem2hex ((unsigned char *) &registers[R15], ptr, 4, 0);
    485  1.1  christos 		  *ptr++ = ';';
    486  1.1  christos 		  *ptr++ = 0;
    487  1.1  christos 
    488  1.1  christos 		  break;
    489  1.1  christos 		}
    490  1.1  christos 	    }
    491  1.1  christos 	  else			/* continuing, not single-stepping */
    492  1.1  christos 	    {
    493  1.1  christos 	      /* OK, about to do a "continue".  First check to see if the
    494  1.7  christos 		 target pc is on an odd boundary (second instruction in the
    495  1.7  christos 		 word).  If so, we must do a single-step first, because
    496  1.7  christos 		 ya can't jump or return back to an odd boundary!  */
    497  1.1  christos 	      if ((registers[PC] & 2) != 0)
    498  1.1  christos 		prepare_to_step (1);
    499  1.1  christos 	    }
    500  1.1  christos 
    501  1.1  christos 	  return;
    502  1.1  christos 
    503  1.1  christos 	case 'D':		/* Detach */
    504  1.1  christos #if 0
    505  1.1  christos 	  /* I am interpreting this to mean, release the board from control
    506  1.1  christos 	     by the remote stub.  To do this, I am restoring the original
    507  1.1  christos 	     (or at least previous) exception vectors.
    508  1.1  christos 	   */
    509  1.1  christos 	  for (i = 0; i < 18; i++)
    510  1.1  christos 	    exceptionHandler (i, save_vectors[i]);
    511  1.1  christos 	  putpacket ("OK");
    512  1.1  christos 	  return;		/* continue the inferior */
    513  1.1  christos #else
    514  1.1  christos 	  strcpy (remcomOutBuffer, "OK");
    515  1.1  christos 	  break;
    516  1.1  christos #endif
    517  1.1  christos 	case 'q':
    518  1.1  christos 	  if (*ptr++ == 'C' &&
    519  1.1  christos 	      *ptr++ == 'R' && *ptr++ == 'C' && *ptr++ == ':')
    520  1.1  christos 	    {
    521  1.1  christos 	      unsigned long start, len, our_crc;
    522  1.1  christos 
    523  1.1  christos 	      if (hexToInt (&ptr, (int *) &start) &&
    524  1.1  christos 		  *ptr++ == ',' && hexToInt (&ptr, (int *) &len))
    525  1.1  christos 		{
    526  1.1  christos 		  remcomOutBuffer[0] = 'C';
    527  1.1  christos 		  our_crc = crc32 ((unsigned char *) start, len, 0xffffffff);
    528  1.1  christos 		  mem2hex ((char *) &our_crc,
    529  1.1  christos 			   &remcomOutBuffer[1], sizeof (long), 0);
    530  1.1  christos 		}		/* else do nothing */
    531  1.1  christos 	    }			/* else do nothing */
    532  1.1  christos 	  break;
    533  1.1  christos 
    534  1.1  christos 	case 'k':		/* kill the program */
    535  1.1  christos 	  continue;
    536  1.1  christos 	}			/* switch */
    537  1.1  christos 
    538  1.1  christos       /* reply to the request */
    539  1.1  christos       putpacket (remcomOutBuffer);
    540  1.1  christos     }
    541  1.1  christos }
    542  1.1  christos 
    543  1.1  christos /* qCRC support */
    544  1.1  christos 
    545  1.6  christos /* Table used by the crc32 function to calculate the checksum.  */
    546  1.1  christos static unsigned long crc32_table[256] = { 0, 0 };
    547  1.1  christos 
    548  1.1  christos static unsigned long
    549  1.1  christos crc32 (unsigned char *buf, int len, unsigned long crc)
    550  1.1  christos {
    551  1.1  christos   if (!crc32_table[1])
    552  1.1  christos     {
    553  1.1  christos       /* Initialize the CRC table and the decoding table. */
    554  1.1  christos       int i, j;
    555  1.1  christos       unsigned long c;
    556  1.1  christos 
    557  1.1  christos       for (i = 0; i < 256; i++)
    558  1.1  christos 	{
    559  1.1  christos 	  for (c = i << 24, j = 8; j > 0; --j)
    560  1.1  christos 	    c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
    561  1.1  christos 	  crc32_table[i] = c;
    562  1.1  christos 	}
    563  1.1  christos     }
    564  1.1  christos 
    565  1.1  christos   while (len--)
    566  1.1  christos     {
    567  1.1  christos       crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
    568  1.1  christos       buf++;
    569  1.1  christos     }
    570  1.1  christos   return crc;
    571  1.1  christos }
    572  1.1  christos 
    573  1.1  christos static int
    574  1.1  christos hex (unsigned char ch)
    575  1.1  christos {
    576  1.1  christos   if ((ch >= 'a') && (ch <= 'f'))
    577  1.1  christos     return (ch - 'a' + 10);
    578  1.1  christos   if ((ch >= '0') && (ch <= '9'))
    579  1.1  christos     return (ch - '0');
    580  1.1  christos   if ((ch >= 'A') && (ch <= 'F'))
    581  1.1  christos     return (ch - 'A' + 10);
    582  1.1  christos   return (-1);
    583  1.1  christos }
    584  1.1  christos 
    585  1.1  christos /* scan for the sequence $<data>#<checksum>     */
    586  1.1  christos 
    587  1.1  christos unsigned char *
    588  1.1  christos getpacket (void)
    589  1.1  christos {
    590  1.1  christos   unsigned char *buffer = &remcomInBuffer[0];
    591  1.1  christos   unsigned char checksum;
    592  1.1  christos   unsigned char xmitcsum;
    593  1.1  christos   int count;
    594  1.1  christos   char ch;
    595  1.1  christos 
    596  1.1  christos   while (1)
    597  1.1  christos     {
    598  1.1  christos       /* wait around for the start character, ignore all other characters */
    599  1.1  christos       while ((ch = getDebugChar ()) != '$')
    600  1.1  christos 	;
    601  1.1  christos 
    602  1.1  christos     retry:
    603  1.1  christos       checksum = 0;
    604  1.1  christos       xmitcsum = -1;
    605  1.1  christos       count = 0;
    606  1.1  christos 
    607  1.1  christos       /* now, read until a # or end of buffer is found */
    608  1.1  christos       while (count < BUFMAX - 1)
    609  1.1  christos 	{
    610  1.1  christos 	  ch = getDebugChar ();
    611  1.1  christos 	  if (ch == '$')
    612  1.1  christos 	    goto retry;
    613  1.1  christos 	  if (ch == '#')
    614  1.1  christos 	    break;
    615  1.1  christos 	  checksum = checksum + ch;
    616  1.1  christos 	  buffer[count] = ch;
    617  1.1  christos 	  count = count + 1;
    618  1.1  christos 	}
    619  1.1  christos       buffer[count] = 0;
    620  1.1  christos 
    621  1.1  christos       if (ch == '#')
    622  1.1  christos 	{
    623  1.1  christos 	  ch = getDebugChar ();
    624  1.1  christos 	  xmitcsum = hex (ch) << 4;
    625  1.1  christos 	  ch = getDebugChar ();
    626  1.1  christos 	  xmitcsum += hex (ch);
    627  1.1  christos 
    628  1.1  christos 	  if (checksum != xmitcsum)
    629  1.1  christos 	    {
    630  1.1  christos 	      if (remote_debug)
    631  1.1  christos 		{
    632  1.1  christos 		  unsigned char buf[16];
    633  1.1  christos 
    634  1.1  christos 		  mem2hex ((unsigned char *) &checksum, buf, 4, 0);
    635  1.1  christos 		  gdb_error ("Bad checksum: my count = %s, ", buf);
    636  1.1  christos 		  mem2hex ((unsigned char *) &xmitcsum, buf, 4, 0);
    637  1.1  christos 		  gdb_error ("sent count = %s\n", buf);
    638  1.1  christos 		  gdb_error (" -- Bad buffer: \"%s\"\n", buffer);
    639  1.1  christos 		}
    640  1.1  christos 	      putDebugChar ('-');	/* failed checksum */
    641  1.1  christos 	    }
    642  1.1  christos 	  else
    643  1.1  christos 	    {
    644  1.1  christos 	      putDebugChar ('+');	/* successful transfer */
    645  1.1  christos 
    646  1.1  christos 	      /* if a sequence char is present, reply the sequence ID */
    647  1.1  christos 	      if (buffer[2] == ':')
    648  1.1  christos 		{
    649  1.1  christos 		  putDebugChar (buffer[0]);
    650  1.1  christos 		  putDebugChar (buffer[1]);
    651  1.1  christos 
    652  1.1  christos 		  return &buffer[3];
    653  1.1  christos 		}
    654  1.1  christos 
    655  1.1  christos 	      return &buffer[0];
    656  1.1  christos 	    }
    657  1.1  christos 	}
    658  1.1  christos     }
    659  1.1  christos }
    660  1.1  christos 
    661  1.1  christos /* send the packet in buffer.  */
    662  1.1  christos 
    663  1.1  christos static void
    664  1.1  christos putpacket (unsigned char *buffer)
    665  1.1  christos {
    666  1.1  christos   unsigned char checksum;
    667  1.1  christos   int count;
    668  1.1  christos   char ch;
    669  1.1  christos 
    670  1.1  christos   /*  $<packet info>#<checksum>. */
    671  1.1  christos   do
    672  1.1  christos     {
    673  1.1  christos       putDebugChar ('$');
    674  1.1  christos       checksum = 0;
    675  1.1  christos       count = 0;
    676  1.1  christos 
    677  1.1  christos       while (ch = buffer[count])
    678  1.1  christos 	{
    679  1.1  christos 	  putDebugChar (ch);
    680  1.1  christos 	  checksum += ch;
    681  1.1  christos 	  count += 1;
    682  1.1  christos 	}
    683  1.1  christos       putDebugChar ('#');
    684  1.1  christos       putDebugChar (hexchars[checksum >> 4]);
    685  1.1  christos       putDebugChar (hexchars[checksum % 16]);
    686  1.1  christos     }
    687  1.1  christos   while (getDebugChar () != '+');
    688  1.1  christos }
    689  1.1  christos 
    690  1.1  christos /* Address of a routine to RTE to if we get a memory fault.  */
    691  1.1  christos 
    692  1.1  christos static void (*volatile mem_fault_routine) () = 0;
    693  1.1  christos 
    694  1.1  christos static void
    695  1.1  christos set_mem_err (void)
    696  1.1  christos {
    697  1.1  christos   mem_err = 1;
    698  1.1  christos }
    699  1.1  christos 
    700  1.1  christos /* Check the address for safe access ranges.  As currently defined,
    701  1.1  christos    this routine will reject the "expansion bus" address range(s).
    702  1.1  christos    To make those ranges useable, someone must implement code to detect
    703  1.1  christos    whether there's anything connected to the expansion bus. */
    704  1.1  christos 
    705  1.1  christos static int
    706  1.1  christos mem_safe (unsigned char *addr)
    707  1.1  christos {
    708  1.1  christos #define BAD_RANGE_ONE_START	((unsigned char *) 0x600000)
    709  1.1  christos #define BAD_RANGE_ONE_END	((unsigned char *) 0xa00000)
    710  1.1  christos #define BAD_RANGE_TWO_START	((unsigned char *) 0xff680000)
    711  1.1  christos #define BAD_RANGE_TWO_END	((unsigned char *) 0xff800000)
    712  1.1  christos 
    713  1.1  christos   if (addr < BAD_RANGE_ONE_START)
    714  1.1  christos     return 1;			/* safe */
    715  1.1  christos   if (addr < BAD_RANGE_ONE_END)
    716  1.1  christos     return 0;			/* unsafe */
    717  1.1  christos   if (addr < BAD_RANGE_TWO_START)
    718  1.1  christos     return 1;			/* safe */
    719  1.1  christos   if (addr < BAD_RANGE_TWO_END)
    720  1.1  christos     return 0;			/* unsafe */
    721  1.1  christos }
    722  1.1  christos 
    723  1.1  christos /* These are separate functions so that they are so short and sweet
    724  1.1  christos    that the compiler won't save any registers (if there is a fault
    725  1.1  christos    to mem_fault, they won't get restored, so there better not be any
    726  1.1  christos    saved).  */
    727  1.1  christos static int
    728  1.1  christos get_char (unsigned char *addr)
    729  1.1  christos {
    730  1.1  christos #if 1
    731  1.1  christos   if (mem_fault_routine && !mem_safe (addr))
    732  1.1  christos     {
    733  1.1  christos       mem_fault_routine ();
    734  1.1  christos       return 0;
    735  1.1  christos     }
    736  1.1  christos #endif
    737  1.1  christos   return *addr;
    738  1.1  christos }
    739  1.1  christos 
    740  1.1  christos static void
    741  1.1  christos set_char (unsigned char *addr, unsigned char val)
    742  1.1  christos {
    743  1.1  christos #if 1
    744  1.1  christos   if (mem_fault_routine && !mem_safe (addr))
    745  1.1  christos     {
    746  1.1  christos       mem_fault_routine ();
    747  1.1  christos       return;
    748  1.1  christos     }
    749  1.1  christos #endif
    750  1.1  christos   *addr = val;
    751  1.1  christos }
    752  1.1  christos 
    753  1.1  christos /* Convert the memory pointed to by mem into hex, placing result in buf.
    754  1.1  christos    Return a pointer to the last char put in buf (null).
    755  1.1  christos    If MAY_FAULT is non-zero, then we should set mem_err in response to
    756  1.1  christos    a fault; if zero treat a fault like any other fault in the stub.  */
    757  1.1  christos 
    758  1.1  christos static unsigned char *
    759  1.1  christos mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
    760  1.1  christos {
    761  1.1  christos   int i;
    762  1.1  christos   unsigned char ch;
    763  1.1  christos 
    764  1.1  christos   if (may_fault)
    765  1.1  christos     mem_fault_routine = set_mem_err;
    766  1.1  christos   for (i = 0; i < count; i++)
    767  1.1  christos     {
    768  1.1  christos       ch = get_char (mem++);
    769  1.1  christos       if (may_fault && mem_err)
    770  1.1  christos 	return (buf);
    771  1.1  christos       *buf++ = hexchars[ch >> 4];
    772  1.1  christos       *buf++ = hexchars[ch % 16];
    773  1.1  christos     }
    774  1.1  christos   *buf = 0;
    775  1.1  christos   if (may_fault)
    776  1.1  christos     mem_fault_routine = 0;
    777  1.1  christos   return (buf);
    778  1.1  christos }
    779  1.1  christos 
    780  1.1  christos /* Convert the hex array pointed to by buf into binary to be placed in mem.
    781  1.1  christos    Return a pointer to the character AFTER the last byte written. */
    782  1.1  christos 
    783  1.1  christos static unsigned char *
    784  1.1  christos hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
    785  1.1  christos {
    786  1.1  christos   int i;
    787  1.1  christos   unsigned char ch;
    788  1.1  christos 
    789  1.1  christos   if (may_fault)
    790  1.1  christos     mem_fault_routine = set_mem_err;
    791  1.1  christos   for (i = 0; i < count; i++)
    792  1.1  christos     {
    793  1.1  christos       ch = hex (*buf++) << 4;
    794  1.1  christos       ch = ch + hex (*buf++);
    795  1.1  christos       set_char (mem++, ch);
    796  1.1  christos       if (may_fault && mem_err)
    797  1.1  christos 	return (mem);
    798  1.1  christos     }
    799  1.1  christos   if (may_fault)
    800  1.1  christos     mem_fault_routine = 0;
    801  1.1  christos   return (mem);
    802  1.1  christos }
    803  1.1  christos 
    804  1.1  christos /* Convert the binary stream in BUF to memory.
    805  1.1  christos 
    806  1.1  christos    Gdb will escape $, #, and the escape char (0x7d).
    807  1.1  christos    COUNT is the total number of bytes to write into
    808  1.1  christos    memory. */
    809  1.1  christos static unsigned char *
    810  1.1  christos bin2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
    811  1.1  christos {
    812  1.1  christos   int i;
    813  1.1  christos   unsigned char ch;
    814  1.1  christos 
    815  1.1  christos   if (may_fault)
    816  1.1  christos     mem_fault_routine = set_mem_err;
    817  1.1  christos   for (i = 0; i < count; i++)
    818  1.1  christos     {
    819  1.1  christos       /* Check for any escaped characters. Be paranoid and
    820  1.7  christos 	 only unescape chars that should be escaped. */
    821  1.1  christos       if (*buf == 0x7d)
    822  1.1  christos 	{
    823  1.1  christos 	  switch (*(buf + 1))
    824  1.1  christos 	    {
    825  1.1  christos 	    case 0x3:		/* # */
    826  1.1  christos 	    case 0x4:		/* $ */
    827  1.1  christos 	    case 0x5d:		/* escape char */
    828  1.1  christos 	      buf++;
    829  1.1  christos 	      *buf |= 0x20;
    830  1.1  christos 	      break;
    831  1.1  christos 	    default:
    832  1.1  christos 	      /* nothing */
    833  1.1  christos 	      break;
    834  1.1  christos 	    }
    835  1.1  christos 	}
    836  1.1  christos 
    837  1.1  christos       set_char (mem++, *buf++);
    838  1.1  christos 
    839  1.1  christos       if (may_fault && mem_err)
    840  1.1  christos 	return mem;
    841  1.1  christos     }
    842  1.1  christos 
    843  1.1  christos   if (may_fault)
    844  1.1  christos     mem_fault_routine = 0;
    845  1.1  christos   return mem;
    846  1.1  christos }
    847  1.1  christos 
    848  1.1  christos /* this function takes the m32r exception vector and attempts to
    849  1.1  christos    translate this number into a unix compatible signal value */
    850  1.1  christos 
    851  1.1  christos static int
    852  1.1  christos computeSignal (int exceptionVector)
    853  1.1  christos {
    854  1.1  christos   int sigval;
    855  1.1  christos   switch (exceptionVector)
    856  1.1  christos     {
    857  1.1  christos     case 0:
    858  1.1  christos       sigval = 23;
    859  1.1  christos       break;			/* I/O trap                    */
    860  1.1  christos     case 1:
    861  1.1  christos       sigval = 5;
    862  1.1  christos       break;			/* breakpoint                  */
    863  1.1  christos     case 2:
    864  1.1  christos       sigval = 5;
    865  1.1  christos       break;			/* breakpoint                  */
    866  1.1  christos     case 3:
    867  1.1  christos       sigval = 5;
    868  1.1  christos       break;			/* breakpoint                  */
    869  1.1  christos     case 4:
    870  1.1  christos       sigval = 5;
    871  1.1  christos       break;			/* breakpoint                  */
    872  1.1  christos     case 5:
    873  1.1  christos       sigval = 5;
    874  1.1  christos       break;			/* breakpoint                  */
    875  1.1  christos     case 6:
    876  1.1  christos       sigval = 5;
    877  1.1  christos       break;			/* breakpoint                  */
    878  1.1  christos     case 7:
    879  1.1  christos       sigval = 5;
    880  1.1  christos       break;			/* breakpoint                  */
    881  1.1  christos     case 8:
    882  1.1  christos       sigval = 5;
    883  1.1  christos       break;			/* breakpoint                  */
    884  1.1  christos     case 9:
    885  1.1  christos       sigval = 5;
    886  1.1  christos       break;			/* breakpoint                  */
    887  1.1  christos     case 10:
    888  1.1  christos       sigval = 5;
    889  1.1  christos       break;			/* breakpoint                  */
    890  1.1  christos     case 11:
    891  1.1  christos       sigval = 5;
    892  1.1  christos       break;			/* breakpoint                  */
    893  1.1  christos     case 12:
    894  1.1  christos       sigval = 5;
    895  1.1  christos       break;			/* breakpoint                  */
    896  1.1  christos     case 13:
    897  1.1  christos       sigval = 5;
    898  1.1  christos       break;			/* breakpoint                  */
    899  1.1  christos     case 14:
    900  1.1  christos       sigval = 5;
    901  1.1  christos       break;			/* breakpoint                  */
    902  1.1  christos     case 15:
    903  1.1  christos       sigval = 5;
    904  1.1  christos       break;			/* breakpoint                  */
    905  1.1  christos     case 16:
    906  1.1  christos       sigval = 10;
    907  1.1  christos       break;			/* BUS ERROR (alignment)       */
    908  1.1  christos     case 17:
    909  1.1  christos       sigval = 2;
    910  1.1  christos       break;			/* INTerrupt                   */
    911  1.1  christos     default:
    912  1.1  christos       sigval = 7;
    913  1.1  christos       break;			/* "software generated"        */
    914  1.1  christos     }
    915  1.1  christos   return (sigval);
    916  1.1  christos }
    917  1.1  christos 
    918  1.1  christos /**********************************************/
    919  1.1  christos /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
    920  1.1  christos /* RETURN NUMBER OF CHARS PROCESSED           */
    921  1.1  christos /**********************************************/
    922  1.1  christos static int
    923  1.1  christos hexToInt (unsigned char **ptr, int *intValue)
    924  1.1  christos {
    925  1.1  christos   int numChars = 0;
    926  1.1  christos   int hexValue;
    927  1.1  christos 
    928  1.1  christos   *intValue = 0;
    929  1.1  christos   while (**ptr)
    930  1.1  christos     {
    931  1.1  christos       hexValue = hex (**ptr);
    932  1.1  christos       if (hexValue >= 0)
    933  1.1  christos 	{
    934  1.1  christos 	  *intValue = (*intValue << 4) | hexValue;
    935  1.1  christos 	  numChars++;
    936  1.1  christos 	}
    937  1.1  christos       else
    938  1.1  christos 	break;
    939  1.1  christos       (*ptr)++;
    940  1.1  christos     }
    941  1.1  christos   return (numChars);
    942  1.1  christos }
    943  1.1  christos 
    944  1.1  christos /*
    945  1.1  christos   Table of branch instructions:
    946  1.1  christos 
    947  1.1  christos   10B6		RTE	return from trap or exception
    948  1.1  christos   1FCr		JMP	jump
    949  1.1  christos   1ECr		JL	jump and link
    950  1.1  christos   7Fxx		BRA	branch
    951  1.1  christos   FFxxxxxx	BRA	branch (long)
    952  1.1  christos   B09rxxxx	BNEZ	branch not-equal-zero
    953  1.1  christos   Br1rxxxx	BNE	branch not-equal
    954  1.1  christos   7Dxx		BNC	branch not-condition
    955  1.1  christos   FDxxxxxx	BNC	branch not-condition (long)
    956  1.1  christos   B0Arxxxx	BLTZ	branch less-than-zero
    957  1.1  christos   B0Crxxxx	BLEZ	branch less-equal-zero
    958  1.1  christos   7Exx		BL	branch and link
    959  1.1  christos   FExxxxxx	BL	branch and link (long)
    960  1.1  christos   B0Drxxxx	BGTZ	branch greater-than-zero
    961  1.1  christos   B0Brxxxx	BGEZ	branch greater-equal-zero
    962  1.1  christos   B08rxxxx	BEQZ	branch equal-zero
    963  1.1  christos   Br0rxxxx	BEQ	branch equal
    964  1.1  christos   7Cxx		BC	branch condition
    965  1.1  christos   FCxxxxxx	BC	branch condition (long)
    966  1.1  christos   */
    967  1.1  christos 
    968  1.1  christos static int
    969  1.1  christos isShortBranch (unsigned char *instr)
    970  1.1  christos {
    971  1.1  christos   unsigned char instr0 = instr[0] & 0x7F;	/* mask off high bit */
    972  1.1  christos 
    973  1.1  christos   if (instr0 == 0x10 && instr[1] == 0xB6)	/* RTE */
    974  1.1  christos     return 1;			/* return from trap or exception */
    975  1.1  christos 
    976  1.1  christos   if (instr0 == 0x1E || instr0 == 0x1F)	/* JL or JMP */
    977  1.1  christos     if ((instr[1] & 0xF0) == 0xC0)
    978  1.1  christos       return 2;			/* jump thru a register */
    979  1.1  christos 
    980  1.1  christos   if (instr0 == 0x7C || instr0 == 0x7D ||	/* BC, BNC, BL, BRA */
    981  1.1  christos       instr0 == 0x7E || instr0 == 0x7F)
    982  1.1  christos     return 3;			/* eight bit PC offset */
    983  1.1  christos 
    984  1.1  christos   return 0;
    985  1.1  christos }
    986  1.1  christos 
    987  1.1  christos static int
    988  1.1  christos isLongBranch (unsigned char *instr)
    989  1.1  christos {
    990  1.1  christos   if (instr[0] == 0xFC || instr[0] == 0xFD ||	/* BRA, BNC, BL, BC */
    991  1.1  christos       instr[0] == 0xFE || instr[0] == 0xFF)	/* 24 bit relative */
    992  1.1  christos     return 4;
    993  1.1  christos   if ((instr[0] & 0xF0) == 0xB0)	/* 16 bit relative */
    994  1.1  christos     {
    995  1.1  christos       if ((instr[1] & 0xF0) == 0x00 ||	/* BNE, BEQ */
    996  1.1  christos 	  (instr[1] & 0xF0) == 0x10)
    997  1.1  christos 	return 5;
    998  1.1  christos       if (instr[0] == 0xB0)	/* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
    999  1.1  christos 	if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
   1000  1.1  christos 	    (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
   1001  1.1  christos 	    (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
   1002  1.1  christos 	  return 6;
   1003  1.1  christos     }
   1004  1.1  christos   return 0;
   1005  1.1  christos }
   1006  1.1  christos 
   1007  1.1  christos /* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
   1008  1.1  christos    then it's a 2-byte instruction, else it's a 4-byte instruction.  */
   1009  1.1  christos 
   1010  1.1  christos #define INSTRUCTION_SIZE(addr) \
   1011  1.1  christos     ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
   1012  1.1  christos 
   1013  1.1  christos static int
   1014  1.1  christos isBranch (unsigned char *instr)
   1015  1.1  christos {
   1016  1.1  christos   if (INSTRUCTION_SIZE (instr) == 2)
   1017  1.1  christos     return isShortBranch (instr);
   1018  1.1  christos   else
   1019  1.1  christos     return isLongBranch (instr);
   1020  1.1  christos }
   1021  1.1  christos 
   1022  1.1  christos static int
   1023  1.1  christos willBranch (unsigned char *instr, int branchCode)
   1024  1.1  christos {
   1025  1.1  christos   switch (branchCode)
   1026  1.1  christos     {
   1027  1.1  christos     case 0:
   1028  1.1  christos       return 0;			/* not a branch */
   1029  1.1  christos     case 1:
   1030  1.1  christos       return 1;			/* RTE */
   1031  1.1  christos     case 2:
   1032  1.1  christos       return 1;			/* JL or JMP    */
   1033  1.1  christos     case 3:			/* BC, BNC, BL, BRA (short) */
   1034  1.1  christos     case 4:			/* BC, BNC, BL, BRA (long) */
   1035  1.1  christos       switch (instr[0] & 0x0F)
   1036  1.1  christos 	{
   1037  1.1  christos 	case 0xC:		/* Branch if Condition Register */
   1038  1.1  christos 	  return (registers[CBR] != 0);
   1039  1.1  christos 	case 0xD:		/* Branch if NOT Condition Register */
   1040  1.1  christos 	  return (registers[CBR] == 0);
   1041  1.1  christos 	case 0xE:		/* Branch and Link */
   1042  1.1  christos 	case 0xF:		/* Branch (unconditional) */
   1043  1.1  christos 	  return 1;
   1044  1.1  christos 	default:		/* oops? */
   1045  1.1  christos 	  return 0;
   1046  1.1  christos 	}
   1047  1.1  christos     case 5:			/* BNE, BEQ */
   1048  1.1  christos       switch (instr[1] & 0xF0)
   1049  1.1  christos 	{
   1050  1.1  christos 	case 0x00:		/* Branch if r1 equal to r2 */
   1051  1.1  christos 	  return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
   1052  1.1  christos 	case 0x10:		/* Branch if r1 NOT equal to r2 */
   1053  1.1  christos 	  return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
   1054  1.1  christos 	default:		/* oops? */
   1055  1.1  christos 	  return 0;
   1056  1.1  christos 	}
   1057  1.1  christos     case 6:			/* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
   1058  1.1  christos       switch (instr[1] & 0xF0)
   1059  1.1  christos 	{
   1060  1.1  christos 	case 0x80:		/* Branch if reg equal to zero */
   1061  1.1  christos 	  return (registers[instr[1] & 0x0F] == 0);
   1062  1.1  christos 	case 0x90:		/* Branch if reg NOT equal to zero */
   1063  1.1  christos 	  return (registers[instr[1] & 0x0F] != 0);
   1064  1.1  christos 	case 0xA0:		/* Branch if reg less than zero */
   1065  1.1  christos 	  return (registers[instr[1] & 0x0F] < 0);
   1066  1.1  christos 	case 0xB0:		/* Branch if reg greater or equal to zero */
   1067  1.1  christos 	  return (registers[instr[1] & 0x0F] >= 0);
   1068  1.1  christos 	case 0xC0:		/* Branch if reg less than or equal to zero */
   1069  1.1  christos 	  return (registers[instr[1] & 0x0F] <= 0);
   1070  1.1  christos 	case 0xD0:		/* Branch if reg greater than zero */
   1071  1.1  christos 	  return (registers[instr[1] & 0x0F] > 0);
   1072  1.1  christos 	default:		/* oops? */
   1073  1.1  christos 	  return 0;
   1074  1.1  christos 	}
   1075  1.1  christos     default:			/* oops? */
   1076  1.1  christos       return 0;
   1077  1.1  christos     }
   1078  1.1  christos }
   1079  1.1  christos 
   1080  1.1  christos static int
   1081  1.1  christos branchDestination (unsigned char *instr, int branchCode)
   1082  1.1  christos {
   1083  1.1  christos   switch (branchCode)
   1084  1.1  christos     {
   1085  1.1  christos     default:
   1086  1.1  christos     case 0:			/* not a branch */
   1087  1.1  christos       return 0;
   1088  1.1  christos     case 1:			/* RTE */
   1089  1.1  christos       return registers[BPC] & ~3;	/* pop BPC into PC */
   1090  1.1  christos     case 2:			/* JL or JMP */
   1091  1.1  christos       return registers[instr[1] & 0x0F] & ~3;	/* jump thru a register */
   1092  1.1  christos     case 3:			/* BC, BNC, BL, BRA (short, 8-bit relative offset) */
   1093  1.1  christos       return (((int) instr) & ~3) + ((char) instr[1] << 2);
   1094  1.1  christos     case 4:			/* BC, BNC, BL, BRA (long, 24-bit relative offset) */
   1095  1.1  christos       return ((int) instr +
   1096  1.1  christos 	      ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) <<
   1097  1.1  christos 	       2));
   1098  1.1  christos     case 5:			/* BNE, BEQ (16-bit relative offset) */
   1099  1.1  christos     case 6:			/* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
   1100  1.1  christos       return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2));
   1101  1.1  christos     }
   1102  1.1  christos 
   1103  1.1  christos   /* An explanatory note: in the last three return expressions, I have
   1104  1.1  christos      cast the most-significant byte of the return offset to char.
   1105  1.1  christos      What this accomplishes is sign extension.  If the other
   1106  1.1  christos      less-significant bytes were signed as well, they would get sign
   1107  1.1  christos      extended too and, if negative, their leading bits would clobber
   1108  1.1  christos      the bits of the more-significant bytes ahead of them.  There are
   1109  1.1  christos      other ways I could have done this, but sign extension from
   1110  1.1  christos      odd-sized integers is always a pain. */
   1111  1.1  christos }
   1112  1.1  christos 
   1113  1.1  christos static void
   1114  1.1  christos branchSideEffects (unsigned char *instr, int branchCode)
   1115  1.1  christos {
   1116  1.1  christos   switch (branchCode)
   1117  1.1  christos     {
   1118  1.1  christos     case 1:			/* RTE */
   1119  1.1  christos       return;			/* I <THINK> this is already handled... */
   1120  1.1  christos     case 2:			/* JL (or JMP) */
   1121  1.1  christos     case 3:			/* BL (or BC, BNC, BRA) */
   1122  1.1  christos     case 4:
   1123  1.1  christos       if ((instr[0] & 0x0F) == 0x0E)	/* branch/jump and link */
   1124  1.1  christos 	registers[R14] = (registers[PC] & ~3) + 4;
   1125  1.1  christos       return;
   1126  1.1  christos     default:			/* any other branch has no side effects */
   1127  1.1  christos       return;
   1128  1.1  christos     }
   1129  1.1  christos }
   1130  1.1  christos 
   1131  1.1  christos static struct STEPPING_CONTEXT
   1132  1.1  christos {
   1133  1.1  christos   int stepping;			/* true when we've started a single-step */
   1134  1.1  christos   unsigned long target_addr;	/* the instr we're trying to execute */
   1135  1.1  christos   unsigned long target_size;	/* the size of the target instr */
   1136  1.1  christos   unsigned long noop_addr;	/* where we've inserted a no-op, if any */
   1137  1.1  christos   unsigned long trap1_addr;	/* the trap following the target instr */
   1138  1.1  christos   unsigned long trap2_addr;	/* the trap at a branch destination, if any */
   1139  1.1  christos   unsigned short noop_save;	/* instruction overwritten by our no-op */
   1140  1.1  christos   unsigned short trap1_save;	/* instruction overwritten by trap1 */
   1141  1.1  christos   unsigned short trap2_save;	/* instruction overwritten by trap2 */
   1142  1.1  christos   unsigned short continue_p;	/* true if NOT returning to gdb after step */
   1143  1.1  christos } stepping;
   1144  1.1  christos 
   1145  1.1  christos /* Function: prepare_to_step
   1146  1.1  christos    Called from handle_exception to prepare the user program to single-step.
   1147  1.1  christos    Places a trap instruction after the target instruction, with special
   1148  1.1  christos    extra handling for branch instructions and for instructions in the
   1149  1.1  christos    second half-word of a word.
   1150  1.1  christos 
   1151  1.1  christos    Returns: True  if we should actually execute the instruction;
   1152  1.1  christos 	    False if we are going to emulate executing the instruction,
   1153  1.1  christos 	    in which case we simply report to GDB that the instruction
   1154  1.1  christos 	    has already been executed.  */
   1155  1.1  christos 
   1156  1.1  christos #define TRAP1  0x10f1;		/* trap #1 instruction */
   1157  1.1  christos #define NOOP   0x7000;		/* noop    instruction */
   1158  1.1  christos 
   1159  1.1  christos static unsigned short trap1 = TRAP1;
   1160  1.1  christos static unsigned short noop = NOOP;
   1161  1.1  christos 
   1162  1.1  christos static int
   1163  1.1  christos prepare_to_step (continue_p)
   1164  1.1  christos      int continue_p;		/* if this isn't REALLY a single-step (see below) */
   1165  1.1  christos {
   1166  1.1  christos   unsigned long pc = registers[PC];
   1167  1.1  christos   int branchCode = isBranch ((unsigned char *) pc);
   1168  1.1  christos   unsigned char *p;
   1169  1.1  christos 
   1170  1.1  christos   /* zero out the stepping context
   1171  1.1  christos      (paranoia -- it should already be zeroed) */
   1172  1.1  christos   for (p = (unsigned char *) &stepping;
   1173  1.1  christos        p < ((unsigned char *) &stepping) + sizeof (stepping); p++)
   1174  1.1  christos     *p = 0;
   1175  1.1  christos 
   1176  1.1  christos   if (branchCode != 0)		/* next instruction is a branch */
   1177  1.1  christos     {
   1178  1.1  christos       branchSideEffects ((unsigned char *) pc, branchCode);
   1179  1.1  christos       if (willBranch ((unsigned char *) pc, branchCode))
   1180  1.1  christos 	registers[PC] = branchDestination ((unsigned char *) pc, branchCode);
   1181  1.1  christos       else
   1182  1.1  christos 	registers[PC] = pc + INSTRUCTION_SIZE (pc);
   1183  1.1  christos       return 0;			/* branch "executed" -- just notify GDB */
   1184  1.1  christos     }
   1185  1.1  christos   else if (((int) pc & 2) != 0)	/* "second-slot" instruction */
   1186  1.1  christos     {
   1187  1.1  christos       /* insert no-op before pc */
   1188  1.1  christos       stepping.noop_addr = pc - 2;
   1189  1.1  christos       stepping.noop_save = *(unsigned short *) stepping.noop_addr;
   1190  1.1  christos       *(unsigned short *) stepping.noop_addr = noop;
   1191  1.1  christos       /* insert trap  after  pc */
   1192  1.1  christos       stepping.trap1_addr = pc + 2;
   1193  1.1  christos       stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
   1194  1.1  christos       *(unsigned short *) stepping.trap1_addr = trap1;
   1195  1.1  christos     }
   1196  1.1  christos   else				/* "first-slot" instruction */
   1197  1.1  christos     {
   1198  1.1  christos       /* insert trap  after  pc */
   1199  1.1  christos       stepping.trap1_addr = pc + INSTRUCTION_SIZE (pc);
   1200  1.1  christos       stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
   1201  1.1  christos       *(unsigned short *) stepping.trap1_addr = trap1;
   1202  1.1  christos     }
   1203  1.1  christos   /* "continue_p" means that we are actually doing a continue, and not
   1204  1.1  christos      being requested to single-step by GDB.  Sometimes we have to do
   1205  1.1  christos      one single-step before continuing, because the PC is on a half-word
   1206  1.1  christos      boundary.  There's no way to simply resume at such an address.  */
   1207  1.1  christos   stepping.continue_p = continue_p;
   1208  1.1  christos   stepping.stepping = 1;	/* starting a single-step */
   1209  1.1  christos   return 1;
   1210  1.1  christos }
   1211  1.1  christos 
   1212  1.1  christos /* Function: finish_from_step
   1213  1.1  christos    Called from handle_exception to finish up when the user program
   1214  1.1  christos    returns from a single-step.  Replaces the instructions that had
   1215  1.1  christos    been overwritten by traps or no-ops,
   1216  1.1  christos 
   1217  1.1  christos    Returns: True  if we should notify GDB that the target stopped.
   1218  1.1  christos 	    False if we only single-stepped because we had to before we
   1219  1.1  christos 	    could continue (ie. we were trying to continue at a
   1220  1.1  christos 	    half-word boundary).  In that case don't notify GDB:
   1221  1.1  christos 	    just "continue continuing".  */
   1222  1.1  christos 
   1223  1.1  christos static int
   1224  1.1  christos finish_from_step (void)
   1225  1.1  christos {
   1226  1.1  christos   if (stepping.stepping)	/* anything to do? */
   1227  1.1  christos     {
   1228  1.1  christos       int continue_p = stepping.continue_p;
   1229  1.1  christos       unsigned char *p;
   1230  1.1  christos 
   1231  1.1  christos       if (stepping.noop_addr)	/* replace instr "under" our no-op */
   1232  1.1  christos 	*(unsigned short *) stepping.noop_addr = stepping.noop_save;
   1233  1.1  christos       if (stepping.trap1_addr)	/* replace instr "under" our trap  */
   1234  1.1  christos 	*(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
   1235  1.1  christos       if (stepping.trap2_addr)	/* ditto our other trap, if any    */
   1236  1.1  christos 	*(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
   1237  1.1  christos 
   1238  1.1  christos       for (p = (unsigned char *) &stepping;	/* zero out the stepping context */
   1239  1.1  christos 	   p < ((unsigned char *) &stepping) + sizeof (stepping); p++)
   1240  1.1  christos 	*p = 0;
   1241  1.1  christos 
   1242  1.1  christos       return !(continue_p);
   1243  1.1  christos     }
   1244  1.1  christos   else				/* we didn't single-step, therefore this must be a legitimate stop */
   1245  1.1  christos     return 1;
   1246  1.1  christos }
   1247  1.1  christos 
   1248  1.1  christos struct PSWreg
   1249  1.1  christos {				/* separate out the bit flags in the PSW register */
   1250  1.1  christos   int pad1:16;
   1251  1.1  christos   int bsm:1;
   1252  1.1  christos   int bie:1;
   1253  1.1  christos   int pad2:5;
   1254  1.1  christos   int bc:1;
   1255  1.1  christos   int sm:1;
   1256  1.1  christos   int ie:1;
   1257  1.1  christos   int pad3:5;
   1258  1.1  christos   int c:1;
   1259  1.1  christos } *psw;
   1260  1.1  christos 
   1261  1.1  christos /* Upon entry the value for LR to save has been pushed.
   1262  1.1  christos    We unpush that so that the value for the stack pointer saved is correct.
   1263  1.1  christos    Upon entry, all other registers are assumed to have not been modified
   1264  1.8  christos    since the interrupt/trap occurred.  */
   1265  1.1  christos 
   1266  1.1  christos asm ("\n\
   1267  1.1  christos stash_registers:\n\
   1268  1.1  christos 	push r0\n\
   1269  1.1  christos 	push r1\n\
   1270  1.1  christos 	seth r1, #shigh(registers)\n\
   1271  1.1  christos 	add3 r1, r1, #low(registers)\n\
   1272  1.1  christos 	pop r0		; r1\n\
   1273  1.1  christos 	st r0, @(4,r1)\n\
   1274  1.1  christos 	pop r0		; r0\n\
   1275  1.1  christos 	st r0, @r1\n\
   1276  1.1  christos 	addi r1, #4	; only add 4 as subsequent saves are `pre inc'\n\
   1277  1.1  christos 	st r2, @+r1\n\
   1278  1.1  christos 	st r3, @+r1\n\
   1279  1.1  christos 	st r4, @+r1\n\
   1280  1.1  christos 	st r5, @+r1\n\
   1281  1.1  christos 	st r6, @+r1\n\
   1282  1.1  christos 	st r7, @+r1\n\
   1283  1.1  christos 	st r8, @+r1\n\
   1284  1.1  christos 	st r9, @+r1\n\
   1285  1.1  christos 	st r10, @+r1\n\
   1286  1.1  christos 	st r11, @+r1\n\
   1287  1.1  christos 	st r12, @+r1\n\
   1288  1.1  christos 	st r13, @+r1    ; fp\n\
   1289  1.1  christos 	pop r0		; lr (r14)\n\
   1290  1.1  christos 	st r0, @+r1\n\
   1291  1.1  christos 	st sp, @+r1	; sp contains right value at this point\n\
   1292  1.1  christos 	mvfc r0, cr0\n\
   1293  1.1  christos 	st r0, @+r1	; cr0 == PSW\n\
   1294  1.1  christos 	mvfc r0, cr1\n\
   1295  1.1  christos 	st r0, @+r1	; cr1 == CBR\n\
   1296  1.1  christos 	mvfc r0, cr2\n\
   1297  1.1  christos 	st r0, @+r1	; cr2 == SPI\n\
   1298  1.1  christos 	mvfc r0, cr3\n\
   1299  1.1  christos 	st r0, @+r1	; cr3 == SPU\n\
   1300  1.1  christos 	mvfc r0, cr6\n\
   1301  1.1  christos 	st r0, @+r1	; cr6 == BPC\n\
   1302  1.1  christos 	st r0, @+r1	; PC  == BPC\n\
   1303  1.1  christos 	mvfaclo r0\n\
   1304  1.1  christos 	st r0, @+r1	; ACCL\n\
   1305  1.1  christos 	mvfachi r0\n\
   1306  1.1  christos 	st r0, @+r1	; ACCH\n\
   1307  1.1  christos 	jmp lr");
   1308  1.1  christos 
   1309  1.1  christos /* C routine to clean up what stash_registers did.
   1310  1.1  christos    It is called after calling stash_registers.
   1311  1.1  christos    This is separate from stash_registers as we want to do this in C
   1312  1.1  christos    but doing stash_registers in C isn't straightforward.  */
   1313  1.1  christos 
   1314  1.1  christos static void
   1315  1.1  christos cleanup_stash (void)
   1316  1.1  christos {
   1317  1.1  christos   psw = (struct PSWreg *) &registers[PSW];	/* fields of PSW register */
   1318  1.1  christos   psw->sm = psw->bsm;		/* fix up pre-trap values of psw fields */
   1319  1.1  christos   psw->ie = psw->bie;
   1320  1.1  christos   psw->c = psw->bc;
   1321  1.1  christos   registers[CBR] = psw->bc;	/* fix up pre-trap "C" register */
   1322  1.1  christos 
   1323  1.1  christos #if 0				/* FIXME: Was in previous version.  Necessary?
   1324  1.1  christos 				   (Remember that we use the "rte" insn to return from the
   1325  1.1  christos 				   trap/interrupt so the values of bsm, bie, bc are important.  */
   1326  1.1  christos   psw->bsm = psw->bie = psw->bc = 0;	/* zero post-trap values */
   1327  1.1  christos #endif
   1328  1.1  christos 
   1329  1.1  christos   /* FIXME: Copied from previous version.  This can probably be deleted
   1330  1.1  christos      since methinks stash_registers has already done this.  */
   1331  1.1  christos   registers[PC] = registers[BPC];	/* pre-trap PC */
   1332  1.1  christos 
   1333  1.1  christos   /* FIXME: Copied from previous version.  Necessary?  */
   1334  1.1  christos   if (psw->sm)			/* copy R15 into (psw->sm ? SPU : SPI) */
   1335  1.1  christos     registers[SPU] = registers[R15];
   1336  1.1  christos   else
   1337  1.1  christos     registers[SPI] = registers[R15];
   1338  1.1  christos }
   1339  1.1  christos 
   1340  1.1  christos asm ("\n\
   1341  1.1  christos restore_and_return:\n\
   1342  1.1  christos 	seth r0, #shigh(registers+8)\n\
   1343  1.1  christos 	add3 r0, r0, #low(registers+8)\n\
   1344  1.1  christos 	ld r2, @r0+	; restore r2\n\
   1345  1.1  christos 	ld r3, @r0+	; restore r3\n\
   1346  1.1  christos 	ld r4, @r0+	; restore r4\n\
   1347  1.1  christos 	ld r5, @r0+	; restore r5\n\
   1348  1.1  christos 	ld r6, @r0+	; restore r6\n\
   1349  1.1  christos 	ld r7, @r0+	; restore r7\n\
   1350  1.1  christos 	ld r8, @r0+	; restore r8\n\
   1351  1.1  christos 	ld r9, @r0+	; restore r9\n\
   1352  1.1  christos 	ld r10, @r0+	; restore r10\n\
   1353  1.1  christos 	ld r11, @r0+	; restore r11\n\
   1354  1.1  christos 	ld r12, @r0+	; restore r12\n\
   1355  1.1  christos 	ld r13, @r0+	; restore r13\n\
   1356  1.1  christos 	ld r14, @r0+	; restore r14\n\
   1357  1.1  christos 	ld r15, @r0+	; restore r15\n\
   1358  1.1  christos 	ld r1, @r0+	; restore cr0 == PSW\n\
   1359  1.1  christos 	mvtc r1, cr0\n\
   1360  1.1  christos 	ld r1, @r0+	; restore cr1 == CBR (no-op, because it's read only)\n\
   1361  1.1  christos 	mvtc r1, cr1\n\
   1362  1.1  christos 	ld r1, @r0+	; restore cr2 == SPI\n\
   1363  1.1  christos 	mvtc r1, cr2\n\
   1364  1.1  christos 	ld r1, @r0+	; restore cr3 == SPU\n\
   1365  1.1  christos 	mvtc r1, cr3\n\
   1366  1.1  christos 	addi r0, #4	; skip BPC\n\
   1367  1.1  christos 	ld r1, @r0+	; restore cr6 (BPC) == PC\n\
   1368  1.1  christos 	mvtc r1, cr6\n\
   1369  1.1  christos 	ld r1, @r0+	; restore ACCL\n\
   1370  1.1  christos 	mvtaclo r1\n\
   1371  1.1  christos 	ld r1, @r0+	; restore ACCH\n\
   1372  1.1  christos 	mvtachi r1\n\
   1373  1.1  christos 	seth r0, #shigh(registers)\n\
   1374  1.1  christos 	add3 r0, r0, #low(registers)\n\
   1375  1.1  christos 	ld r1, @(4,r0)	; restore r1\n\
   1376  1.1  christos 	ld r0, @r0	; restore r0\n\
   1377  1.1  christos 	rte");
   1378  1.1  christos 
   1379  1.1  christos /* General trap handler, called after the registers have been stashed.
   1380  1.1  christos    NUM is the trap/exception number.  */
   1381  1.1  christos 
   1382  1.1  christos static void
   1383  1.1  christos process_exception (int num)
   1384  1.1  christos {
   1385  1.1  christos   cleanup_stash ();
   1386  1.1  christos   asm volatile ("\n\
   1387  1.1  christos 	seth r1, #shigh(stackPtr)\n\
   1388  1.1  christos 	add3 r1, r1, #low(stackPtr)\n\
   1389  1.1  christos 	ld r15, @r1		; setup local stack (protect user stack)\n\
   1390  1.1  christos 	mv r0, %0\n\
   1391  1.1  christos 	bl handle_exception\n\
   1392  1.1  christos 	bl restore_and_return"::"r" (num):"r0", "r1");
   1393  1.1  christos }
   1394  1.1  christos 
   1395  1.1  christos void _catchException0 ();
   1396  1.1  christos 
   1397  1.1  christos asm ("\n\
   1398  1.1  christos _catchException0:\n\
   1399  1.1  christos 	push lr\n\
   1400  1.1  christos 	bl stash_registers\n\
   1401  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1402  1.1  christos 	ldi r0, #0\n\
   1403  1.1  christos 	bl process_exception");
   1404  1.1  christos 
   1405  1.1  christos void _catchException1 ();
   1406  1.1  christos 
   1407  1.1  christos asm ("\n\
   1408  1.1  christos _catchException1:\n\
   1409  1.1  christos 	push lr\n\
   1410  1.1  christos 	bl stash_registers\n\
   1411  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1412  1.1  christos 	bl cleanup_stash\n\
   1413  1.1  christos 	seth r1, #shigh(stackPtr)\n\
   1414  1.1  christos 	add3 r1, r1, #low(stackPtr)\n\
   1415  1.1  christos 	ld r15, @r1		; setup local stack (protect user stack)\n\
   1416  1.1  christos 	seth r1, #shigh(registers + 21*4) ; PC\n\
   1417  1.1  christos 	add3 r1, r1, #low(registers + 21*4)\n\
   1418  1.1  christos 	ld r0, @r1\n\
   1419  1.1  christos 	addi r0, #-4		; back up PC for breakpoint trap.\n\
   1420  1.1  christos 	st r0, @r1		; FIXME: what about bp in right slot?\n\
   1421  1.1  christos 	ldi r0, #1\n\
   1422  1.1  christos 	bl handle_exception\n\
   1423  1.1  christos 	bl restore_and_return");
   1424  1.1  christos 
   1425  1.1  christos void _catchException2 ();
   1426  1.1  christos 
   1427  1.1  christos asm ("\n\
   1428  1.1  christos _catchException2:\n\
   1429  1.1  christos 	push lr\n\
   1430  1.1  christos 	bl stash_registers\n\
   1431  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1432  1.1  christos 	ldi r0, #2\n\
   1433  1.1  christos 	bl process_exception");
   1434  1.1  christos 
   1435  1.1  christos void _catchException3 ();
   1436  1.1  christos 
   1437  1.1  christos asm ("\n\
   1438  1.1  christos _catchException3:\n\
   1439  1.1  christos 	push lr\n\
   1440  1.1  christos 	bl stash_registers\n\
   1441  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1442  1.1  christos 	ldi r0, #3\n\
   1443  1.1  christos 	bl process_exception");
   1444  1.1  christos 
   1445  1.1  christos void _catchException4 ();
   1446  1.1  christos 
   1447  1.1  christos asm ("\n\
   1448  1.1  christos _catchException4:\n\
   1449  1.1  christos 	push lr\n\
   1450  1.1  christos 	bl stash_registers\n\
   1451  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1452  1.1  christos 	ldi r0, #4\n\
   1453  1.1  christos 	bl process_exception");
   1454  1.1  christos 
   1455  1.1  christos void _catchException5 ();
   1456  1.1  christos 
   1457  1.1  christos asm ("\n\
   1458  1.1  christos _catchException5:\n\
   1459  1.1  christos 	push lr\n\
   1460  1.1  christos 	bl stash_registers\n\
   1461  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1462  1.1  christos 	ldi r0, #5\n\
   1463  1.1  christos 	bl process_exception");
   1464  1.1  christos 
   1465  1.1  christos void _catchException6 ();
   1466  1.1  christos 
   1467  1.1  christos asm ("\n\
   1468  1.1  christos _catchException6:\n\
   1469  1.1  christos 	push lr\n\
   1470  1.1  christos 	bl stash_registers\n\
   1471  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1472  1.1  christos 	ldi r0, #6\n\
   1473  1.1  christos 	bl process_exception");
   1474  1.1  christos 
   1475  1.1  christos void _catchException7 ();
   1476  1.1  christos 
   1477  1.1  christos asm ("\n\
   1478  1.1  christos _catchException7:\n\
   1479  1.1  christos 	push lr\n\
   1480  1.1  christos 	bl stash_registers\n\
   1481  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1482  1.1  christos 	ldi r0, #7\n\
   1483  1.1  christos 	bl process_exception");
   1484  1.1  christos 
   1485  1.1  christos void _catchException8 ();
   1486  1.1  christos 
   1487  1.1  christos asm ("\n\
   1488  1.1  christos _catchException8:\n\
   1489  1.1  christos 	push lr\n\
   1490  1.1  christos 	bl stash_registers\n\
   1491  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1492  1.1  christos 	ldi r0, #8\n\
   1493  1.1  christos 	bl process_exception");
   1494  1.1  christos 
   1495  1.1  christos void _catchException9 ();
   1496  1.1  christos 
   1497  1.1  christos asm ("\n\
   1498  1.1  christos _catchException9:\n\
   1499  1.1  christos 	push lr\n\
   1500  1.1  christos 	bl stash_registers\n\
   1501  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1502  1.1  christos 	ldi r0, #9\n\
   1503  1.1  christos 	bl process_exception");
   1504  1.1  christos 
   1505  1.1  christos void _catchException10 ();
   1506  1.1  christos 
   1507  1.1  christos asm ("\n\
   1508  1.1  christos _catchException10:\n\
   1509  1.1  christos 	push lr\n\
   1510  1.1  christos 	bl stash_registers\n\
   1511  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1512  1.1  christos 	ldi r0, #10\n\
   1513  1.1  christos 	bl process_exception");
   1514  1.1  christos 
   1515  1.1  christos void _catchException11 ();
   1516  1.1  christos 
   1517  1.1  christos asm ("\n\
   1518  1.1  christos _catchException11:\n\
   1519  1.1  christos 	push lr\n\
   1520  1.1  christos 	bl stash_registers\n\
   1521  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1522  1.1  christos 	ldi r0, #11\n\
   1523  1.1  christos 	bl process_exception");
   1524  1.1  christos 
   1525  1.1  christos void _catchException12 ();
   1526  1.1  christos 
   1527  1.1  christos asm ("\n\
   1528  1.1  christos _catchException12:\n\
   1529  1.1  christos 	push lr\n\
   1530  1.1  christos 	bl stash_registers\n\
   1531  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1532  1.1  christos 	ldi r0, #12\n\
   1533  1.1  christos 	bl process_exception");
   1534  1.1  christos 
   1535  1.1  christos void _catchException13 ();
   1536  1.1  christos 
   1537  1.1  christos asm ("\n\
   1538  1.1  christos _catchException13:\n\
   1539  1.1  christos 	push lr\n\
   1540  1.1  christos 	bl stash_registers\n\
   1541  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1542  1.1  christos 	ldi r0, #13\n\
   1543  1.1  christos 	bl process_exception");
   1544  1.1  christos 
   1545  1.1  christos void _catchException14 ();
   1546  1.1  christos 
   1547  1.1  christos asm ("\n\
   1548  1.1  christos _catchException14:\n\
   1549  1.1  christos 	push lr\n\
   1550  1.1  christos 	bl stash_registers\n\
   1551  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1552  1.1  christos 	ldi r0, #14\n\
   1553  1.1  christos 	bl process_exception");
   1554  1.1  christos 
   1555  1.1  christos void _catchException15 ();
   1556  1.1  christos 
   1557  1.1  christos asm ("\n\
   1558  1.1  christos _catchException15:\n\
   1559  1.1  christos 	push lr\n\
   1560  1.1  christos 	bl stash_registers\n\
   1561  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1562  1.1  christos 	ldi r0, #15\n\
   1563  1.1  christos 	bl process_exception");
   1564  1.1  christos 
   1565  1.1  christos void _catchException16 ();
   1566  1.1  christos 
   1567  1.1  christos asm ("\n\
   1568  1.1  christos _catchException16:\n\
   1569  1.1  christos 	push lr\n\
   1570  1.1  christos 	bl stash_registers\n\
   1571  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1572  1.1  christos 	ldi r0, #16\n\
   1573  1.1  christos 	bl process_exception");
   1574  1.1  christos 
   1575  1.1  christos void _catchException17 ();
   1576  1.1  christos 
   1577  1.1  christos asm ("\n\
   1578  1.1  christos _catchException17:\n\
   1579  1.1  christos 	push lr\n\
   1580  1.1  christos 	bl stash_registers\n\
   1581  1.1  christos 	; Note that at this point the pushed value of `lr' has been popped\n\
   1582  1.1  christos 	ldi r0, #17\n\
   1583  1.1  christos 	bl process_exception");
   1584  1.1  christos 
   1585  1.1  christos 
   1586  1.1  christos /* this function is used to set up exception handlers for tracing and
   1587  1.1  christos    breakpoints */
   1588  1.1  christos void
   1589  1.1  christos set_debug_traps (void)
   1590  1.1  christos {
   1591  1.1  christos   /*  extern void remcomHandler(); */
   1592  1.1  christos   int i;
   1593  1.1  christos 
   1594  1.1  christos   for (i = 0; i < 18; i++)	/* keep a copy of old vectors */
   1595  1.1  christos     if (save_vectors[i] == 0)	/* only copy them the first time */
   1596  1.1  christos       save_vectors[i] = getExceptionHandler (i);
   1597  1.1  christos 
   1598  1.1  christos   stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
   1599  1.1  christos 
   1600  1.1  christos   exceptionHandler (0, _catchException0);
   1601  1.1  christos   exceptionHandler (1, _catchException1);
   1602  1.1  christos   exceptionHandler (2, _catchException2);
   1603  1.1  christos   exceptionHandler (3, _catchException3);
   1604  1.1  christos   exceptionHandler (4, _catchException4);
   1605  1.1  christos   exceptionHandler (5, _catchException5);
   1606  1.1  christos   exceptionHandler (6, _catchException6);
   1607  1.1  christos   exceptionHandler (7, _catchException7);
   1608  1.1  christos   exceptionHandler (8, _catchException8);
   1609  1.1  christos   exceptionHandler (9, _catchException9);
   1610  1.1  christos   exceptionHandler (10, _catchException10);
   1611  1.1  christos   exceptionHandler (11, _catchException11);
   1612  1.1  christos   exceptionHandler (12, _catchException12);
   1613  1.1  christos   exceptionHandler (13, _catchException13);
   1614  1.1  christos   exceptionHandler (14, _catchException14);
   1615  1.1  christos   exceptionHandler (15, _catchException15);
   1616  1.1  christos   exceptionHandler (16, _catchException16);
   1617  1.1  christos   /*  exceptionHandler (17, _catchException17); */
   1618  1.1  christos 
   1619  1.1  christos   initialized = 1;
   1620  1.1  christos }
   1621  1.1  christos 
   1622  1.1  christos /* This function will generate a breakpoint exception.  It is used at the
   1623  1.1  christos    beginning of a program to sync up with a debugger and can be used
   1624  1.1  christos    otherwise as a quick means to stop program execution and "break" into
   1625  1.1  christos    the debugger. */
   1626  1.1  christos 
   1627  1.1  christos #define BREAKPOINT() asm volatile ("	trap #2");
   1628  1.1  christos 
   1629  1.1  christos void
   1630  1.1  christos breakpoint (void)
   1631  1.1  christos {
   1632  1.1  christos   if (initialized)
   1633  1.1  christos     BREAKPOINT ();
   1634  1.1  christos }
   1635  1.1  christos 
   1636  1.1  christos /* STDOUT section:
   1637  1.1  christos    Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
   1638  1.1  christos    Functions: gdb_putchar(char ch)
   1639  1.7  christos 	      gdb_puts(char *str)
   1640  1.7  christos 	      gdb_write(char *str, int len)
   1641  1.7  christos 	      gdb_error(char *format, char *parm)
   1642  1.1  christos 	      */
   1643  1.1  christos 
   1644  1.1  christos /* Function: gdb_putchar(int)
   1645  1.1  christos    Make gdb write a char to stdout.
   1646  1.1  christos    Returns: the char */
   1647  1.1  christos 
   1648  1.1  christos static int
   1649  1.1  christos gdb_putchar (int ch)
   1650  1.1  christos {
   1651  1.1  christos   char buf[4];
   1652  1.1  christos 
   1653  1.1  christos   buf[0] = 'O';
   1654  1.1  christos   buf[1] = hexchars[ch >> 4];
   1655  1.1  christos   buf[2] = hexchars[ch & 0x0F];
   1656  1.1  christos   buf[3] = 0;
   1657  1.1  christos   putpacket (buf);
   1658  1.1  christos   return ch;
   1659  1.1  christos }
   1660  1.1  christos 
   1661  1.1  christos /* Function: gdb_write(char *, int)
   1662  1.1  christos    Make gdb write n bytes to stdout (not assumed to be null-terminated).
   1663  1.1  christos    Returns: number of bytes written */
   1664  1.1  christos 
   1665  1.1  christos static int
   1666  1.1  christos gdb_write (char *data, int len)
   1667  1.1  christos {
   1668  1.1  christos   char *buf, *cpy;
   1669  1.1  christos   int i;
   1670  1.1  christos 
   1671  1.1  christos   buf = remcomOutBuffer;
   1672  1.1  christos   buf[0] = 'O';
   1673  1.1  christos   i = 0;
   1674  1.1  christos   while (i < len)
   1675  1.1  christos     {
   1676  1.1  christos       for (cpy = buf + 1;
   1677  1.1  christos 	   i < len && cpy < buf + sizeof (remcomOutBuffer) - 3; i++)
   1678  1.1  christos 	{
   1679  1.1  christos 	  *cpy++ = hexchars[data[i] >> 4];
   1680  1.1  christos 	  *cpy++ = hexchars[data[i] & 0x0F];
   1681  1.1  christos 	}
   1682  1.1  christos       *cpy = 0;
   1683  1.1  christos       putpacket (buf);
   1684  1.1  christos     }
   1685  1.1  christos   return len;
   1686  1.1  christos }
   1687  1.1  christos 
   1688  1.1  christos /* Function: gdb_puts(char *)
   1689  1.1  christos    Make gdb write a null-terminated string to stdout.
   1690  1.1  christos    Returns: the length of the string */
   1691  1.1  christos 
   1692  1.1  christos static int
   1693  1.1  christos gdb_puts (char *str)
   1694  1.1  christos {
   1695  1.1  christos   return gdb_write (str, strlen (str));
   1696  1.1  christos }
   1697  1.1  christos 
   1698  1.1  christos /* Function: gdb_error(char *, char *)
   1699  1.1  christos    Send an error message to gdb's stdout.
   1700  1.1  christos    First string may have 1 (one) optional "%s" in it, which
   1701  1.1  christos    will cause the optional second string to be inserted.  */
   1702  1.1  christos 
   1703  1.1  christos static void
   1704  1.1  christos gdb_error (char *format, char *parm)
   1705  1.1  christos {
   1706  1.1  christos   char buf[400], *cpy;
   1707  1.1  christos   int len;
   1708  1.1  christos 
   1709  1.1  christos   if (remote_debug)
   1710  1.1  christos     {
   1711  1.1  christos       if (format && *format)
   1712  1.1  christos 	len = strlen (format);
   1713  1.1  christos       else
   1714  1.1  christos 	return;			/* empty input */
   1715  1.1  christos 
   1716  1.1  christos       if (parm && *parm)
   1717  1.1  christos 	len += strlen (parm);
   1718  1.1  christos 
   1719  1.1  christos       for (cpy = buf; *format;)
   1720  1.1  christos 	{
   1721  1.1  christos 	  if (format[0] == '%' && format[1] == 's')	/* include second string */
   1722  1.1  christos 	    {
   1723  1.1  christos 	      format += 2;	/* advance two chars instead of just one */
   1724  1.1  christos 	      while (parm && *parm)
   1725  1.1  christos 		*cpy++ = *parm++;
   1726  1.1  christos 	    }
   1727  1.1  christos 	  else
   1728  1.1  christos 	    *cpy++ = *format++;
   1729  1.1  christos 	}
   1730  1.1  christos       *cpy = '\0';
   1731  1.1  christos       gdb_puts (buf);
   1732  1.1  christos     }
   1733  1.1  christos }
   1734  1.1  christos 
   1735  1.1  christos static unsigned char *
   1736  1.1  christos strcpy (unsigned char *dest, const unsigned char *src)
   1737  1.1  christos {
   1738  1.1  christos   unsigned char *ret = dest;
   1739  1.1  christos 
   1740  1.1  christos   if (dest && src)
   1741  1.1  christos     {
   1742  1.1  christos       while (*src)
   1743  1.1  christos 	*dest++ = *src++;
   1744  1.1  christos       *dest = 0;
   1745  1.1  christos     }
   1746  1.1  christos   return ret;
   1747  1.1  christos }
   1748  1.1  christos 
   1749  1.1  christos static int
   1750  1.1  christos strlen (const unsigned char *src)
   1751  1.1  christos {
   1752  1.1  christos   int ret;
   1753  1.1  christos 
   1754  1.1  christos   for (ret = 0; *src; src++)
   1755  1.1  christos     ret++;
   1756  1.1  christos 
   1757  1.1  christos   return ret;
   1758  1.1  christos }
   1759  1.1  christos 
   1760  1.1  christos #if 0
   1761  1.1  christos void
   1762  1.1  christos exit (code)
   1763  1.1  christos      int code;
   1764  1.1  christos {
   1765  1.1  christos   _exit (code);
   1766  1.1  christos }
   1767  1.1  christos 
   1768  1.1  christos int
   1769  1.1  christos atexit (void *p)
   1770  1.1  christos {
   1771  1.1  christos   return 0;
   1772  1.1  christos }
   1773  1.1  christos 
   1774  1.1  christos void
   1775  1.1  christos abort (void)
   1776  1.1  christos {
   1777  1.1  christos   _exit (1);
   1778  1.1  christos }
   1779  1.1  christos #endif
   1780