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