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 *) ®isters[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 *) ®isters[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 *) ®isters[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 *) ®isters[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 *) ®isters[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, ®no) && *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 *) ®isters[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 *) ®isters[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 *) ®isters[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 *) ®isters[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 *) ®isters[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