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