2 *******************************************************************************
6 * Description: main routines for PA RISC monitor stub
8 * Created: Mon Nov 1 10:00:36 1993
9 * Modified: Fri Nov 12 15:14:23 1993 (Robert Quist) quist@hpfcrdq
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 $
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
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
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
70 * ? What was the last sigval ? SNN (signal NN)
72 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
77 * All commands and responses are sent with a packet which includes a
78 * checksum. A packet consists of :
80 * $<packet info>#<checksum>.
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.
92 * $m0,10#2a +$00010203040506070809101112131415#42
94 ****************************************************************************/
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 */
126 #define NUMGPRBYTES 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
,
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
};
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
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 */
220 /*========================================================================== */
222 /* Convert ch from a hex digit to an int */
228 if (ch
>= 'a' && ch
<= 'f')
230 if (ch
>= '0' && ch
<= '9')
232 if (ch
>= 'A' && ch
<= 'F')
237 /* scan for the sequence $<data>#<checksum> */
243 unsigned char checksum
;
244 unsigned char xmitcsum
;
251 /* wait around for the start character, ignore all other characters */
253 while ((ch
= getDebugChar()) != '$') ;
260 /* now, read until a # or end of buffer is found */
261 while (count
< BUFMAX
)
266 checksum
= checksum
+ ch
;
278 xmitcsum
= hex(getDebugChar()) << 4;
279 xmitcsum
|= hex(getDebugChar());
282 /* Humans shouldn't have to figure out checksums to type to it. */
286 if (checksum
!= xmitcsum
)
287 putDebugChar('-'); /* failed checksum */
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. */
311 unsigned char *buffer
;
313 unsigned char checksum
;
317 /* $<packet info>#<checksum>. */
325 while (ch
= buffer
[count
])
327 if (! putDebugChar(ch
))
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,
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
)
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;
369 *buf
++ = hexchars
[ch
>> 4];
370 *buf
++ = hexchars
[ch
& 0xf];
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
)
395 for (i
=0; i
<count
; i
++)
397 ch
= hex(*buf
++) << 4;
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;
412 /* Set up exception handlers for traceing and breakpoints */
417 unsigned int R_addr
[33];
418 unsigned int *Raddr_ptr
;
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;
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. */
445 /* Convert the PA-RISC hardware trap number to a unix signal number. */
451 struct hard_trap_info
*ht
;
453 for (ht
= hard_trap_info
; ht
->tt
&& ht
->signo
; ht
++)
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.
466 hexToInt(ptr
, intValue
)
477 hexValue
= hex(**ptr
);
481 *intValue
= (*intValue
<< 4) | hexValue
;
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 */
521 /* reply to host that an exception has occurred */
522 sigval
= computeSignal(tt
);
523 ptr
= remcomOutBuffer
;
526 *ptr
++ = hexchars
[sigval
>> 4];
527 *ptr
++ = hexchars
[sigval
& 0xf];
529 /* could be lots of stuff here like PC and SP registers */
533 putpacket(remcomOutBuffer
);
537 remcomOutBuffer
[0] = 0;
539 getpacket(remcomInBuffer
);
540 switch (remcomInBuffer
[0])
543 remcomOutBuffer
[0] = 'S';
544 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
545 remcomOutBuffer
[2] = hexchars
[sigval
& 0xf];
546 remcomOutBuffer
[3] = 0;
550 /* toggle debug flag */
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 */
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");
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
)
579 && hexToInt(&ptr
, &length
))
581 if (mem2hex((char *)addr
, remcomOutBuffer
, length
, 1))
584 strcpy (remcomOutBuffer
, "E03");
587 strcpy(remcomOutBuffer
,"E01");
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
)
597 && hexToInt(&ptr
, &length
)
600 if (hex2mem(ptr
, (char *)addr
, length
, 1))
601 strcpy(remcomOutBuffer
, "OK");
603 strcpy(remcomOutBuffer
, "E03");
606 strcpy(remcomOutBuffer
, "E02");
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.
625 return 0; /* execute GO */
627 /* kill the program */
628 case 'k' : /* do nothing */
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.
645 return 1; /* execute Single Step */
649 case 't': /* Test feature */
652 case 'r': /* Reset */
656 Disabled until we can unscrew
this properly
658 case 'b': /* bBB... Set baud rate to BB... */
661 extern void set_timer_3();
663 ptr
= &remcomInBuffer
[1];
664 if (!hexToInt(&ptr
, &baudrate
))
666 strcpy(remcomOutBuffer
,"B01");
670 /* Convert baud rate to uart clock divider */
683 strcpy(remcomOutBuffer
,"B02");
687 putpacket("OK 2"); /* Ack before changing speed */
688 set_timer_3(baudrate
); /* Set it */
694 /* reply to the request */
695 putpacket(remcomOutBuffer
);
697 print ("\r\nEscaped handle_exception\r\n");