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