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