fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / libgloss / hp74x / pa_stub.c
blob296492175622afcd1fa948e4781f6274323678d4
1 /* -*-C-*-
2 *******************************************************************************
4 * File: pa_stub.c
5 * RCS: $Header$
6 * Description: main routines for PA RISC monitor stub
7 * Author: Robert Quist
8 * Created: Mon Nov 1 10:00:36 1993
9 * Modified: Fri Nov 12 15:14:23 1993 (Robert Quist) quist@hpfcrdq
10 * Language: C
11 * Package: N/A
12 * Status: Experimental (Do Not Distribute)
14 *******************************************************************************
17 /****************************************************************************
19 THIS SOFTWARE IS NOT COPYRIGHTED
21 HP offers the following for use in the public domain. HP makes no
22 warranty with regard to the software or it's performance and the
23 user accepts the software "AS IS" with all faults.
25 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
26 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
27 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 ****************************************************************************/
31 /****************************************************************************
33 * Description: low level support for gdb debugger. $
35 * Considerations: only works on target hardware $
37 * NOTES: See Below $
39 * To enable debugger support, two things need to happen.
41 * One, a call to set_debug_traps() is necessary in order to allow
42 * any breakpoints or error conditions to be properly intercepted and
43 * reported to gdb.
45 * Two, a breakpoint needs to be generated to begin communication.
46 * This is most easily accomplished by a call to breakpoint().
47 * breakpoint() simulates a breakpoint
50 *************
52 * The following gdb commands are supported:
54 * command function Return value
56 * g return the value of the CPU registers hex data or ENN
57 * G set the value of the CPU registers OK or ENN
59 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
60 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
62 * c Resume at current address SNN ( signal NN)
63 * cAA..AA Continue at address AA..AA SNN
65 * s Step one instruction SNN
66 * sAA..AA Step one instruction from AA..AA SNN
68 * k kill
70 * ? What was the last sigval ? SNN (signal NN)
72 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
73 * baud rate
76 ************
77 * All commands and responses are sent with a packet which includes a
78 * checksum. A packet consists of :
80 * $<packet info>#<checksum>.
82 * where
83 * <packet info> :: <characters representing the command or response>
84 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
86 * When a packet is received, it is first acknowledged with either '+' or '-'.
87 * '+' indicates a successful transfer. '-' indicates a failed transfer.
89 * Example:
91 * Host: Reply:
92 * $m0,10#2a +$00010203040506070809101112131415#42
94 ****************************************************************************/
95 #include <signal.h>
96 #include "hppa-defs.h"
98 /************************************************************************
100 * external low-level support
102 #define OPT_PDC_CACHE 5
103 #define OPT_PDC_ADD_VALID 12
104 #define PGZ_MEM_PDC 0x0388 /* location of PDC_ENTRY in memory */
105 #define CALL_PDC (*(int (*)())((int *)(*((int *)PGZ_MEM_PDC))))
107 extern putDebugChar(); /* write a single character */
108 extern getDebugChar(); /* read and return a single char */
109 extern FICE(); /* flush i cache entry */
110 extern INLINE_BREAK(); /* break for user call */
112 #define RADDR_ALIGN(s,r) (s = ((unsigned int *) ((((int) r ) + 7 ) & 0xFFFFFFF8)))
114 /************************************************************************/
115 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
116 /* at least NUMREGBYTES*2 are needed for register packets */
118 #define BUFMAX 2048
120 #define NUMGPRS 32
121 #define NUMSRS 8
122 #define NUMCRS 32
123 #define NUMSPCLS 3
124 #define NUMFPRS 32
126 #define NUMGPRBYTES 4
127 #define NUMSRBYTES 4
128 #define NUMCRBYTES 4
129 #define NUMSPCLBYTES 4
130 #define NUMFPRBYTES 8
132 /* Number of bytes of registers. */
133 #define NUMREGBYTES \
134 ( (NUMGPRS * NUMGPRBYTES) \
135 + (NUMSRS * NUMSRBYTES) \
136 + (NUMCRS * NUMCRBYTES) \
137 + (NUMSPCLS * NUMSPCLBYTES) \
138 + (NUMFPRS * NUMFPRBYTES) \
142 enum regnames {GR0, GR1, GR2, GR3, GR4, GR5, GR6, GR7,
143 GR8, GR9, GR10, GR11, GR12, GR13, GR14, GR15,
144 GR16, GR17, GR18, GR19, GR20, GR21, GR22, GR23,
145 GR24, GR25, GR26, GR27, GR28, GR29, GR30, GR31,
147 SR0, SR1, SR2, SR3, SR4, SR5, SR6, SR7,
149 CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7,
150 CR8, CR9, CR10, CR11, CR12, CR13, CR14, CR15,
151 CR16, CR17H,CR18H,CR19, CR20, CR21, CR22, CR23,
152 CR24, CR25, CR26, CR27, CR28, CR29, CR30, CR31,
154 CR17T,CR18T,CPUD0 };
156 enum fregnames {FPR0, FPR1, FPR2, FPR3, FPR4, FPR5, FPR6, FPR7,
157 FPR8, FPR9, FPR10, FPR11, FPR12, FPR13, FPR14, FPR15,
158 FPR16, FPR17, FPR18, FPR19, FPR20, FPR21, FPR22, FPR23,
159 FPR24, FPR25, FPR26, FPR27, FPR28, FPR29, FPR30, FPR31 };
161 #define PC CR18H
162 #define NPC CR18T
163 #define SP GR30
165 struct registers {
166 int intregs[NUMGPRS + NUMSRS + NUMCRS + NUMSPCLS];
167 int fpregs [NUMFPRS * 2];
169 /* Global Variables */
171 static int initialized = 0; /* !0 means we've been initialized */
172 static unsigned char hexchars[]="0123456789abcdef";
173 static unsigned char remcomInBuffer[BUFMAX];
174 static unsigned char remcomOutBuffer[BUFMAX];
175 static unsigned int i_cache_params[6];
177 /* This table contains the mapping between PA hardware exception
178 types, and signals, which are primarily what GDB understands. It also
179 indicates which hardware traps we need to commandeer when initializing
180 the stub.
182 The only two currently used are Recovery counter (single stepping)
183 and Break trap ( break points ).
186 static struct hard_trap_info
188 unsigned char tt; /* Trap number for PA-RISC */
189 unsigned char signo; /* Signal that we map this trap into */
190 } hard_trap_info[] = {
191 /* 1 High priority machine check */
192 /* 2 Power failure interrupt*/
193 /* 3 Recovery counter -- init */
194 /* 4 External interrupt */
195 /* 5 Low priority machine check */
196 {6, SIGSEGV}, /* Instruction TLB miss/page fault */
197 {7, SIGSEGV}, /* Memory protection */
198 {8, SIGILL}, /* Illegal instruction */
199 {9, SIGTRAP}, /* Break instruction -- init */
200 {10,SIGILL}, /* Privileged instruction */
201 {11,SIGILL}, /* Privileged register */
202 {12,SIGUSR1}, /* Overflow */
203 {13,SIGUSR2}, /* Conditional */
204 {14,SIGEMT}, /* Assist Exception */
205 {15,SIGSEGV}, /* Data TLB miss/page fault */
206 {16,SIGSEGV}, /* Non-access Instruction TLB miss */
207 {17,SIGSEGV}, /* Non-access Data TLB miss/page fault */
208 {18,SIGSEGV}, /* Data memory protection/ unaligned data reference */
209 {19,SIGTRAP}, /* Data memory break */
210 {20,SIGSEGV}, /* TLB dirty bit */
211 {21,SIGSEGV}, /* Page reference */
212 {22,SIGEMT}, /* Assist emulation */
213 {23,SIGILL}, /* Higher-privilege */
214 {24,SIGILL}, /* Lower-privilege */
215 {25,SIGTRAP}, /* Taken branch */
216 {0, 0} /* Must be last */
219 /* Functions */
220 /*========================================================================== */
222 /* Convert ch from a hex digit to an int */
224 static int
225 hex(ch)
226 unsigned char ch;
228 if (ch >= 'a' && ch <= 'f')
229 return ch-'a'+10;
230 if (ch >= '0' && ch <= '9')
231 return ch-'0';
232 if (ch >= 'A' && ch <= 'F')
233 return ch-'A'+10;
234 return -1;
237 /* scan for the sequence $<data>#<checksum> */
239 static void
240 getpacket(buffer)
241 char *buffer;
243 unsigned char checksum;
244 unsigned char xmitcsum;
245 int i;
246 int count;
247 unsigned char ch;
251 /* wait around for the start character, ignore all other characters */
252 strobe();
253 while ((ch = getDebugChar()) != '$') ;
255 checksum = 0;
256 xmitcsum = -1;
258 count = 0;
260 /* now, read until a # or end of buffer is found */
261 while (count < BUFMAX)
263 ch = getDebugChar();
264 if (ch == '#')
265 break;
266 checksum = checksum + ch;
267 buffer[count] = ch;
268 count = count + 1;
271 if (count >= BUFMAX)
272 continue;
274 buffer[count] = 0;
276 if (ch == '#')
278 xmitcsum = hex(getDebugChar()) << 4;
279 xmitcsum |= hex(getDebugChar());
281 #if TESTING
282 /* Humans shouldn't have to figure out checksums to type to it. */
283 putDebugChar ('+');
284 return;
285 #endif
286 if (checksum != xmitcsum)
287 putDebugChar('-'); /* failed checksum */
288 else
290 putDebugChar('+'); /* successful transfer */
291 /* if a sequence char is present, reply the sequence ID */
292 if (buffer[2] == ':')
294 putDebugChar(buffer[0]);
295 putDebugChar(buffer[1]);
296 /* remove sequence chars from buffer */
297 count = strlen(buffer);
298 for (i=3; i <= count; i++)
299 buffer[i-3] = buffer[i];
304 while (checksum != xmitcsum);
307 /* send the packet in buffer. */
309 static void
310 putpacket(buffer)
311 unsigned char *buffer;
313 unsigned char checksum;
314 int count;
315 unsigned char ch;
317 /* $<packet info>#<checksum>. */
321 putDebugChar('$');
322 checksum = 0;
323 count = 0;
325 while (ch = buffer[count])
327 if (! putDebugChar(ch))
328 return;
329 checksum += ch;
330 count += 1;
333 putDebugChar('#');
334 putDebugChar(hexchars[checksum >> 4]);
335 putDebugChar(hexchars[checksum & 0xf]);
336 } while (getDebugChar() != '+');
339 /* Convert the memory pointed to by mem into hex, placing result in buf.
340 * Return a pointer to the last char put in buf (null), in case of mem fault,
341 * return 0.
342 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
343 * a 0, else treat a fault like any other fault in the stub.
346 static unsigned char *
347 mem2hex(mem, buf, count, may_fault)
348 unsigned char *mem;
349 unsigned char *buf;
350 int count;
351 int may_fault;
353 unsigned char ch;
354 int check_addr,
355 new_addr;
357 check_addr = 0;
359 while (count-- > 0)
361 if (may_fault)
362 { new_addr = ((int) (mem+3)) & 0xFFFFFFF8;
363 if (new_addr != check_addr)
364 { check_addr = new_addr;
365 if (pdc_call(OPT_PDC_ADD_VALID,0,check_addr)) return 0;
368 ch = *mem++;
369 *buf++ = hexchars[ch >> 4];
370 *buf++ = hexchars[ch & 0xf];
373 *buf = 0;
375 return buf;
378 /* convert the hex array pointed to by buf into binary to be placed in mem
379 * return a pointer to the character AFTER the last byte written */
381 static unsigned char *
382 hex2mem(buf, mem, count, may_fault)
383 unsigned char *buf;
384 unsigned char *mem;
385 int count;
386 int may_fault;
388 int i;
389 unsigned int ch;
390 int check_addr,
391 new_addr;
393 check_addr = 0;
395 for (i=0; i<count; i++)
397 ch = hex(*buf++) << 4;
398 ch |= hex(*buf++);
399 if (may_fault)
400 { new_addr = ((int)(mem+3)) & 0xFFFFFFF8;
401 if (new_addr != check_addr)
402 { check_addr = new_addr;
403 if (pdc_call(OPT_PDC_ADD_VALID,0,check_addr)) return 0;
406 *mem++ = ch;
409 return mem;
412 /* Set up exception handlers for traceing and breakpoints */
414 void
415 set_debug_traps()
417 unsigned int R_addr[33];
418 unsigned int *Raddr_ptr;
420 setup_vectors();
422 /* get cache params for use by flush_i_cache */
423 RADDR_ALIGN(Raddr_ptr,R_addr);
425 if (pdc_call(OPT_PDC_CACHE,0,Raddr_ptr,0))
426 i_cache_params[0] = -1;
427 else
428 i_cache_params[0] = R_addr[0];
430 i_cache_params[1] = Raddr_ptr[1];
431 i_cache_params[2] = Raddr_ptr[2];
432 i_cache_params[3] = Raddr_ptr[3];
433 i_cache_params[4] = Raddr_ptr[4];
434 i_cache_params[5] = Raddr_ptr[5];
436 /* In case GDB is started before us, ack any packets (presumably
437 "$?#xx") sitting there. */
439 putDebugChar ('+');
441 initialized = 1;
445 /* Convert the PA-RISC hardware trap number to a unix signal number. */
447 static int
448 computeSignal(tt)
449 int tt;
451 struct hard_trap_info *ht;
453 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
454 if (ht->tt == tt)
455 return ht->signo;
457 return SIGHUP; /* default for things we don't know about */
461 * While we find nice hex chars, build an int.
462 * Return number of chars processed.
465 static int
466 hexToInt(ptr, intValue)
467 unsigned char **ptr;
468 int *intValue;
470 int numChars = 0;
471 int hexValue;
473 *intValue = 0;
475 while (**ptr)
477 hexValue = hex(**ptr);
478 if (hexValue < 0)
479 break;
481 *intValue = (*intValue << 4) | hexValue;
482 numChars ++;
484 (*ptr)++;
487 return (numChars);
490 void
491 flush_i_cache()
494 unsigned int addr,count,loop;
496 if (i_cache_params[0] <= 0) return;
498 addr = i_cache_params[2];
499 for (count = 0; count < i_cache_params[4]; count++)
500 { for ( loop = 0; loop < i_cache_params[5]; loop++) FICE(addr);
501 addr = addr + i_cache_params[3];
506 * This function does all command procesing for interfacing to gdb.
507 return of 0 will execute DEBUG_GO (continue)
508 return of 1 will execute DEBUG_SS (single step)
512 handle_exception (registers,tt)
513 unsigned long *registers;
514 int tt; /* Trap type */
516 int sigval;
517 int addr;
518 int length;
519 unsigned char *ptr;
521 /* reply to host that an exception has occurred */
522 sigval = computeSignal(tt);
523 ptr = remcomOutBuffer;
525 *ptr++ = 'T';
526 *ptr++ = hexchars[sigval >> 4];
527 *ptr++ = hexchars[sigval & 0xf];
529 /* could be lots of stuff here like PC and SP registers */
531 *ptr++ = 0;
533 putpacket(remcomOutBuffer);
535 while (1)
537 remcomOutBuffer[0] = 0;
539 getpacket(remcomInBuffer);
540 switch (remcomInBuffer[0])
542 case '?':
543 remcomOutBuffer[0] = 'S';
544 remcomOutBuffer[1] = hexchars[sigval >> 4];
545 remcomOutBuffer[2] = hexchars[sigval & 0xf];
546 remcomOutBuffer[3] = 0;
547 break;
549 case 'd':
550 /* toggle debug flag */
551 led_putnum (16);
552 break;
554 case 'g': /* return the value of the CPU registers */
556 ptr = remcomOutBuffer;
557 /* GR0..GR31 SR0..SR7 CR0..CR31 specials */
558 ptr = mem2hex((char *)registers, ptr, NUMREGBYTES, 0);
559 /* need to add floating point registers */
561 break;
563 case 'G': /* set the value of the CPU registers - return OK */
565 ptr = &remcomInBuffer[1];
566 /* GR0..GR31 SR0..SR7 CR0..CR31 specials */
567 hex2mem(ptr, (char *)registers, NUMREGBYTES, 0);
568 strcpy(remcomOutBuffer,"OK 1");
570 break;
572 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
573 /* Try to read %x,%x. */
575 ptr = &remcomInBuffer[1];
577 if (hexToInt(&ptr, &addr)
578 && *ptr++ == ','
579 && hexToInt(&ptr, &length))
581 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
582 break;
584 strcpy (remcomOutBuffer, "E03");
586 else
587 strcpy(remcomOutBuffer,"E01");
588 break;
590 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
591 /* Try to read '%x,%x:'. */
593 ptr = &remcomInBuffer[1];
595 if (hexToInt(&ptr, &addr)
596 && *ptr++ == ','
597 && hexToInt(&ptr, &length)
598 && *ptr++ == ':')
600 if (hex2mem(ptr, (char *)addr, length, 1))
601 strcpy(remcomOutBuffer, "OK");
602 else
603 strcpy(remcomOutBuffer, "E03");
605 else
606 strcpy(remcomOutBuffer, "E02");
607 break;
609 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
610 /* try to read optional parameter, pc unchanged if no parm */
612 ptr = &remcomInBuffer[1];
613 if (hexToInt(&ptr, &addr))
615 registers[PC] = addr;
616 registers[NPC] = addr + 4;
619 /* Need to flush the instruction cache here, as we may have deposited a
620 breakpoint, and the icache probably has no way of knowing that a data ref to
621 some location may have changed something that is in the instruction cache.
624 flush_i_cache();
625 return 0; /* execute GO */
627 /* kill the program */
628 case 'k' : /* do nothing */
629 break;
631 case 's' : /* single step */
632 /* try to read optional parameter, pc unchanged if no parm */
634 ptr = &remcomInBuffer[1];
635 if (hexToInt(&ptr, &addr))
637 registers[PC] = addr;
638 registers[NPC] = addr + 4;
640 /* Need to flush the instruction cache here, as we may have deposited a
641 breakpoint, and the icache probably has no way of knowing that a data ref to
642 some location may have changed something that is in the instruction cache.
644 flush_i_cache();
645 return 1; /* execute Single Step */
646 break;
648 #if TESTING1
649 case 't': /* Test feature */
650 break;
651 #endif
652 case 'r': /* Reset */
653 break;
655 #if TESTING2
656 Disabled until we can unscrew this properly
658 case 'b': /* bBB... Set baud rate to BB... */
660 int baudrate;
661 extern void set_timer_3();
663 ptr = &remcomInBuffer[1];
664 if (!hexToInt(&ptr, &baudrate))
666 strcpy(remcomOutBuffer,"B01");
667 break;
670 /* Convert baud rate to uart clock divider */
671 switch (baudrate)
673 case 38400:
674 baudrate = 16;
675 break;
676 case 19200:
677 baudrate = 33;
678 break;
679 case 9600:
680 baudrate = 65;
681 break;
682 default:
683 strcpy(remcomOutBuffer,"B02");
684 goto x1;
687 putpacket("OK 2"); /* Ack before changing speed */
688 set_timer_3(baudrate); /* Set it */
690 x1: break;
691 #endif
692 } /* switch */
694 /* reply to the request */
695 putpacket(remcomOutBuffer);
697 print ("\r\nEscaped handle_exception\r\n");