fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / libgloss / mips / lsi33k-stub.c
blobdc0b86ac63502ed4428487a6f6c70cee60b361dc
1 /****************************************************************************
3 * Module name: remcom.c $
4 * Revision: 1.34 $
5 * Date: 91/03/09 12:29:49 $
6 * Contributor: Lake Stevens Instrument Division$
8 * Description: low level support for gdb debugger. $
10 * Considerations: only works on target hardware $
12 * Written by: Glenn Engel $
13 * ModuleState: Experimental $
15 * NOTES: See Below $
17 * Modified for SPARC by Stu Grossman, Cygnus Support.
19 * This code has been extensively tested on the Fujitsu SPARClite demo board.
21 * To enable debugger support, two things need to happen. One, a
22 * call to set_debug_traps() is necessary in order to allow any breakpoints
23 * or error conditions to be properly intercepted and reported to gdb.
24 * Two, a breakpoint needs to be generated to begin communication. This
25 * is most easily accomplished by a call to breakpoint(). Breakpoint()
26 * simulates a breakpoint by executing a trap #1.
28 *************
30 * The following gdb commands are supported:
32 * command function Return value
34 * g return the value of the CPU registers hex data or ENN
35 * G set the value of the CPU registers OK or ENN
37 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
38 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
40 * c Resume at current address SNN ( signal NN)
41 * cAA..AA Continue at address AA..AA SNN
43 * s Step one instruction SNN
44 * sAA..AA Step one instruction from AA..AA SNN
46 * k kill
48 * ? What was the last sigval ? SNN (signal NN)
50 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
51 * baud rate
53 * All commands and responses are sent with a packet which includes a
54 * checksum. A packet consists of
56 * $<packet info>#<checksum>.
58 * where
59 * <packet info> :: <characters representing the command or response>
60 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
62 * When a packet is received, it is first acknowledged with either '+' or '-'.
63 * '+' indicates a successful transfer. '-' indicates a failed transfer.
65 * Example:
67 * Host: Reply:
68 * $m0,10#2a +$00010203040506070809101112131415#42
70 ****************************************************************************/
72 #include <string.h>
73 #include <signal.h>
74 #include "dbgmon.h"
75 #include "parser.h"
76 #include "ctype.h"
78 /************************************************************************
80 * external low-level support routines
83 extern putchar(); /* write a single character */
84 extern getchar(); /* read and return a single char */
86 /************************************************************************/
88 /* Stuff for stdio-like gets_debugger_check() */
90 #define CTRL(x) ('x'&0x1f)
91 #define DEL 0x7f
92 #define INTR CTRL(C)
93 #define BELL 0x7
94 #define PROMPT "? "
96 #define BUFSIZE 512 /* Big enough for register packets */
98 static int initialized = 0; /* !0 means we've been initialized */
100 static char hexchars[]="0123456789abcdef";
102 extern unsigned int _regs[]; /* Saved registers from client */
104 /* Convert ch from a hex digit to an int */
106 static int
107 hex(ch)
108 unsigned char ch;
110 if (ch >= 'a' && ch <= 'f')
111 return ch-'a'+10;
112 if (ch >= '0' && ch <= '9')
113 return ch-'0';
114 if (ch >= 'A' && ch <= 'F')
115 return ch-'A'+10;
116 return -1;
119 /* scan for the sequence $<data>#<checksum> */
121 static void
122 getpacket(buffer)
123 char *buffer;
125 unsigned char checksum;
126 unsigned char xmitcsum;
127 int i;
128 int count;
129 unsigned char ch;
131 /* At this point, the start character ($) has been received through
132 * the debug monitor parser. Get the remaining characters and
133 * process them.
136 checksum = 0;
137 xmitcsum = -1;
138 count = 0;
140 /* read until a # or end of buffer is found */
142 while (count < BUFSIZE)
144 ch = getchar();
145 if (ch == '#')
146 break;
147 checksum = checksum + ch;
148 buffer[count] = ch;
149 count = count + 1;
152 if (count >= BUFSIZE)
153 buffer[count] = 0;
155 if (ch == '#')
157 xmitcsum = hex(getchar()) << 4;
158 xmitcsum |= hex(getchar());
159 #if 0
160 /* Humans shouldn't have to figure out checksums to type to it. */
161 putchar ('+');
162 return;
163 #endif
165 if (checksum != xmitcsum)
167 putchar('-'); /* failed checksum */
168 return; /* Back to monitor loop */
170 else
172 putchar('+'); /* successful transfer */
174 /* if a sequence char is present, reply the sequence ID */
176 if (buffer[2] == ':')
178 putchar(buffer[0]);
179 putchar(buffer[1]);
181 /* remove sequence chars from buffer */
183 count = strlen(buffer);
184 for (i=3; i <= count; i++)
185 buffer[i-3] = buffer[i];
188 /* Buffer command received- go and process it. */
196 /* send the packet in buffer. */
198 static void
199 putpacket(buffer)
200 unsigned char *buffer;
202 unsigned char checksum;
203 int count;
204 unsigned char ch;
206 /* $<packet info>#<checksum>. */
209 putchar('$');
210 checksum = 0;
211 count = 0;
213 while (ch = buffer[count])
215 if (! putchar(ch))
216 return;
217 checksum += ch;
218 count += 1;
221 putchar('#');
222 putchar(hexchars[checksum >> 4]);
223 putchar(hexchars[checksum & 0xf]);
226 while (getchar() != '+');
229 static char remcomInBuffer[BUFSIZE];
230 static char remcomOutBuffer[BUFSIZE];
232 /* Indicate to caller of mem2hex or hex2mem that there has been an error. */
234 static volatile int mem_err = 0;
236 /* Convert the memory pointed to by mem into hex, placing result in buf.
237 * Return a pointer to the last char put in buf (null), in case of mem fault,
238 * return 0.
239 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
240 * a 0, else treat a fault like any other fault in the stub.
243 static unsigned char *
244 mem2hex(mem, buf, count, may_fault)
245 unsigned char *mem;
246 unsigned char *buf;
247 int count;
248 int may_fault;
250 unsigned char ch;
252 while (count-- > 0)
254 ch = *mem++;
255 if (mem_err)
256 return 0;
257 *buf++ = hexchars[ch >> 4];
258 *buf++ = hexchars[ch & 0xf];
261 *buf = 0;
263 return buf;
266 /* convert the hex array pointed to by buf into binary to be placed in mem
267 * return a pointer to the character AFTER the last byte written */
269 static char *
270 hex2mem(buf, mem, count, may_fault)
271 unsigned char *buf;
272 unsigned char *mem;
273 int count;
274 int may_fault;
276 int i;
277 unsigned char ch;
279 for (i=0; i<count; i++)
281 ch = hex(*buf++) << 4;
282 ch |= hex(*buf++);
283 *mem++ = ch;
284 if (mem_err)
285 return 0;
288 return mem;
291 /* This table contains the mapping between SPARC hardware trap types, and
292 signals, which are primarily what GDB understands. It also indicates
293 which hardware traps we need to commandeer when initializing the stub. */
295 static struct hard_trap_info
297 unsigned char tt; /* Trap type code for SPARClite */
298 unsigned char signo; /* Signal that we map this trap into */
299 } hard_trap_info[] = {
300 {0x06, SIGSEGV}, /* instruction access error */
301 {0x0a, SIGILL}, /* privileged instruction */
302 {0x0a, SIGILL}, /* illegal instruction */
303 {0x0b, SIGEMT}, /* cp disabled */
304 {0x07, SIGSEGV}, /* data access exception */
305 {0x09, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
306 {0, 0} /* Must be last */
309 /* Convert the SPARC hardware trap type code to a unix signal number. */
311 static int
312 computeSignal(tt)
313 int tt;
315 struct hard_trap_info *ht;
317 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
318 if (ht->tt == tt)
319 return ht->signo;
321 return SIGHUP; /* default for things we don't know about */
325 * While we find nice hex chars, build an int.
326 * Return number of chars processed.
329 static int
330 hexToInt(char **ptr, int *intValue)
332 int numChars = 0;
333 int hexValue;
335 *intValue = 0;
337 while (**ptr)
339 hexValue = hex(**ptr);
340 if (hexValue < 0)
341 break;
343 *intValue = (*intValue << 4) | hexValue;
344 numChars ++;
346 (*ptr)++;
349 return (numChars);
352 /* This function lets GDB know that an exception has occured. */
354 static void
355 debug_handle_exception ()
357 int tt; /* Trap type */
358 int sigval;
359 char *ptr;
361 tt = (_regs[R_CAUSE] >> 2) & 0x0f;
363 /* reply to host that an exception has occurred */
364 sigval = computeSignal(tt);
365 ptr = remcomOutBuffer;
367 *ptr++ = 'T';
368 *ptr++ = hexchars[sigval >> 4];
369 *ptr++ = hexchars[sigval & 0xf];
371 *ptr++ = hexchars[R_EPC >> 4];
372 *ptr++ = hexchars[R_EPC & 0xf];
373 *ptr++ = ':';
374 ptr = mem2hex((char *)&_regs[R_EPC], ptr, 4, 0);
375 *ptr++ = ';';
377 *ptr++ = hexchars[R_FP >> 4];
378 *ptr++ = hexchars[R_FP & 0xf];
379 *ptr++ = ':';
380 ptr = mem2hex((char *)&_regs[R_FP], ptr, 4, 0);
381 *ptr++ = ';';
383 *ptr++ = hexchars[R_SP >> 4];
384 *ptr++ = hexchars[R_SP & 0xf];
385 *ptr++ = ':';
386 ptr = mem2hex((char *)&_regs[R_SP], ptr, 4, 0);
387 *ptr++ = ';';
389 *ptr++ = 0;
391 putpacket(remcomOutBuffer);
393 return;
397 void process_packet()
400 char *ptr;
401 int length;
402 int addr;
403 int sigval;
404 int tt; /* Trap type */
406 remcomOutBuffer[0] = 0;
407 getpacket(remcomInBuffer);
408 switch (remcomInBuffer[0])
411 /* Return Last SIGVAL */
413 case '?':
414 tt = (_regs[R_CAUSE] >> 2) & 0x0f;
415 sigval = computeSignal(tt);
416 remcomOutBuffer[0] = 'S';
417 remcomOutBuffer[1] = hexchars[sigval >> 4];
418 remcomOutBuffer[2] = hexchars[sigval & 0xf];
419 remcomOutBuffer[3] = 0;
420 break;
422 /* toggle debug flag */
424 case 'd':
425 break;
427 /* Return the values of the CPU registers */
429 case 'g':
430 ptr = remcomOutBuffer;
431 ptr = mem2hex((char *)_regs, ptr, 32 * 4, 0); /* General Purpose Registers */
432 ptr = mem2hex((char *)&_regs[R_EPC], ptr, 9 * 4, 0); /* CP0 Registers */
433 break;
435 /* set the value of the CPU registers - return OK */
437 case 'G':
438 ptr = &remcomInBuffer[1];
439 hex2mem(ptr, (char *)_regs, 32 * 4, 0); /* General Purpose Registers */
440 hex2mem(ptr + 32 * 4 * 2, (char *)&_regs[R_EPC], 9 * 4, 0); /* CP0 Registers */
441 strcpy(remcomOutBuffer,"OK");
442 break;
444 /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
446 case 'm':
447 ptr = &remcomInBuffer[1];
448 if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length))
450 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
451 break;
452 strcpy (remcomOutBuffer, "E03");
454 else
455 strcpy(remcomOutBuffer,"E01");
456 break;
458 /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
460 case 'M':
461 ptr = &remcomInBuffer[1];
462 if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length) && *ptr++ == ':')
464 if (hex2mem(ptr, (char *)addr, length, 1))
465 strcpy(remcomOutBuffer, "OK");
466 else
467 strcpy(remcomOutBuffer, "E03");
469 else
470 strcpy(remcomOutBuffer, "E02");
471 break;
473 /* cAA..AA Continue at address AA..AA(optional) */
475 case 'c':
477 /* try to read optional parameter, pc unchanged if no parm */
479 ptr = &remcomInBuffer[1];
480 if (hexToInt(&ptr, &addr))
482 gdb_go ( addr );
484 else
486 dbg_cont();
488 return;
490 /* kill the program */
492 case 'k':
493 break;
495 /* Reset */
497 case 'r':
498 break;
500 /* switch */
504 /* Reply to the request */
506 putpacket(remcomOutBuffer);
511 * gets_debugger_check - This is the same as the stdio gets, but we also
512 * check for a leading $ in the buffer. This so we
513 * gracefully handle the GDB protocol packets.
516 char *
517 gets_debugger_check(buf)
518 char *buf;
520 register char c;
521 char *bufp;
523 bufp = buf;
524 for (;;)
526 c = getchar();
527 switch (c)
530 /* quote next char */
532 case '$':
533 if ( buf == bufp )
534 process_packet();
535 break;
537 case CTRL(V):
538 c = getchar();
539 if (bufp < &buf[LINESIZE-3])
541 rmw_byte (bufp++,c);
542 showchar(c);
544 else
546 putchar(BELL);
548 break;
550 case '\n':
551 case '\r':
552 putchar('\n');
553 rmw_byte (bufp,0);
554 return(buf);
556 case CTRL(H):
557 case DEL:
558 if (bufp > buf)
560 bufp--;
561 putchar(CTRL(H));
562 putchar(' ');
563 putchar(CTRL(H));
565 break;
567 case CTRL(U):
568 if (bufp > buf)
570 printf("^U\n%s", PROMPT);
571 bufp = buf;
573 break;
575 case '\t':
576 c = ' ';
578 default:
580 * Make sure there's room for this character
581 * plus a trailing \n and 0 byte
583 if (isprint(c) && bufp < &buf[LINESIZE-3])
585 rmw_byte ( bufp++, c );
586 putchar(c);
588 else
590 putchar(BELL);
592 break;