xref: /csrg-svn/sys/hp300/hp300/kgdb_stub.c (revision 43413)
141475Smckusick /*
241475Smckusick  * Copyright (c) 1988 University of Utah.
341475Smckusick  * Copyright (c) 1990 The Regents of the University of California.
441475Smckusick  * All rights reserved.
541475Smckusick  *
641475Smckusick  * This code is derived from software contributed to Berkeley by
741475Smckusick  * the Systems Programming Group of the University of Utah Computer
841475Smckusick  * Science Department.
941475Smckusick  *
1041475Smckusick  * %sccs.include.redist.c%
1141475Smckusick  *
12*43413Shibler  *	@(#)kgdb_stub.c	7.3 (Berkeley) 06/22/90
1341475Smckusick  */
1441475Smckusick 
1541475Smckusick /*
1641475Smckusick  *
1741475Smckusick  *    The following gdb commands are supported:
1841475Smckusick  *
1941475Smckusick  * command          function                               Return value
2041475Smckusick  *
2141475Smckusick  *    g             return the value of the CPU registers  hex data or ENN
2241475Smckusick  *    G             set the value of the CPU registers     OK or ENN
2341475Smckusick  *
2441475Smckusick  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
2541475Smckusick  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
2641475Smckusick  *
2741475Smckusick  *    c             Resume at current address              SNN   ( signal NN)
2841475Smckusick  *    cAA..AA       Continue at address AA..AA             SNN
2941475Smckusick  *
3041475Smckusick  *    s             Step one instruction                   SNN
3141475Smckusick  *    sAA..AA       Step one instruction from AA..AA       SNN
3241475Smckusick  *
3341475Smckusick  *    k             kill
3441475Smckusick  *
3541475Smckusick  *    ?             What was the last sigval ?             SNN   (signal NN)
3641475Smckusick  *
3741475Smckusick  * All commands and responses are sent with a packet which includes a
3841475Smckusick  * checksum.  A packet consists of
3941475Smckusick  *
4041475Smckusick  * $<packet info>#<checksum>.
4141475Smckusick  *
4241475Smckusick  * where
4341475Smckusick  * <packet info> :: <characters representing the command or response>
4441475Smckusick  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
4541475Smckusick  *
4641475Smckusick  * When a packet is received, it is first acknowledged with either '+' or '-'.
4741475Smckusick  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
4841475Smckusick  *
4941475Smckusick  * Example:
5041475Smckusick  *
5141475Smckusick  * Host:                  Reply:
5241475Smckusick  * $m0,10#2a               +$00010203040506070809101112131415#42
5341475Smckusick  *
5441475Smckusick  ****************************************************************************/
5541475Smckusick 
5641475Smckusick #ifdef KGDB
5741475Smckusick #include "param.h"
5841475Smckusick #include "systm.h"
5941475Smckusick #include "trap.h"
6041475Smckusick #include "cpu.h"
6141475Smckusick #include "psl.h"
6241475Smckusick #include "reg.h"
6341475Smckusick #include "frame.h"
6441475Smckusick #include "buf.h"
6541475Smckusick 
6641475Smckusick extern void printf();
6741475Smckusick extern void bcopy();
6841475Smckusick extern int kernacc();
6941475Smckusick extern void chgkprot();
7041475Smckusick 
7141475Smckusick /* # of additional (beyond 4) bytes in 680x0 exception frame format n */
7241475Smckusick static int frame_bytes[16] = {
7341475Smckusick 	4,	4,	8,	4,
7441475Smckusick 	4,	4,	4,	4,
7541475Smckusick 	54,	16,	28,	88,
7641475Smckusick 	4,	4,	4,	4
7741475Smckusick };
7841475Smckusick 
7941475Smckusick #define USER    040             /* (XXX from trap.c) user-mode flag in type */
8041475Smckusick 
8141475Smckusick /*
8241475Smckusick  * BUFMAX defines the maximum number of characters in inbound/outbound
8341475Smckusick  * buffers.  At least NUMREGBYTES*2 are needed for register packets.
8441475Smckusick  */
8541475Smckusick #define BUFMAX 512
8641475Smckusick 
8742367Smckusick #ifndef KGDBDEV
8842367Smckusick #define KGDBDEV -1
8942367Smckusick #endif
9042367Smckusick #ifndef KGDBRATE
9142367Smckusick #define KGDBRATE 9600
9242367Smckusick #endif
9342367Smckusick 
9442367Smckusick int kgdb_dev = KGDBDEV;		/* remote debugging device (-1 if none) */
9542367Smckusick int kgdb_rate = KGDBRATE;	/* remote debugging baud rate */
9641475Smckusick int kgdb_debug_init = 0;	/* != 0 waits for remote at system init */
9741475Smckusick int kgdb_debug = 0;		/* > 0 prints command & checksum errors */
9841475Smckusick 
9942367Smckusick #include "../hp300/cons.h"
10041475Smckusick 
10142367Smckusick #define GETC	\
10242367Smckusick 	(constab[major(kgdb_dev)].cn_getc ? \
10342367Smckusick 		(*constab[major(kgdb_dev)].cn_getc)(kgdb_dev) : 0)
10442367Smckusick #define PUTC(c)	{ \
10542367Smckusick 	if (constab[major(kgdb_dev)].cn_putc) \
10642367Smckusick 		(*constab[major(kgdb_dev)].cn_putc)(kgdb_dev, c); \
10742367Smckusick }
10842367Smckusick 
10941475Smckusick static char hexchars[] = "0123456789abcdef";
11041475Smckusick 
11141475Smckusick /*
11241475Smckusick  * There are 180 bytes of registers on a 68020 w/68881.  Many of the fpa
11341475Smckusick  * registers are 12 byte (96 bit) registers.
11441475Smckusick  */
11541475Smckusick #define NUMREGBYTES 180
11641475Smckusick 
11741475Smckusick static char inbuffer[BUFMAX];
11841475Smckusick static char outbuffer[BUFMAX];
11941475Smckusick 
12041475Smckusick static inline int
12141475Smckusick hex(ch)
12241475Smckusick 	char ch;
12341475Smckusick {
12441475Smckusick 	if ((ch >= '0') && (ch <= '9'))
12541475Smckusick 		return (ch - '0');
12641475Smckusick 	if ((ch >= 'a') && (ch <= 'f'))
12741475Smckusick 		return (ch - ('a' - 10));
12841475Smckusick 	return (0);
12941475Smckusick }
13041475Smckusick 
13141475Smckusick /* scan for the sequence $<data>#<checksum>     */
13241475Smckusick static void
13341475Smckusick getpacket(char *buffer)
13441475Smckusick {
13541475Smckusick 	unsigned char checksum;
13641475Smckusick 	unsigned char xmitcsum;
13741475Smckusick 	int i;
13841475Smckusick 	int count;
13941475Smckusick 	char ch;
14041475Smckusick 
14141475Smckusick 	do {
14241475Smckusick 		/*
14341475Smckusick 		 * wait around for the start character, ignore all other
14441475Smckusick 		 * characters
14541475Smckusick 		 */
14641475Smckusick 		while ((ch = GETC) != '$')
14741475Smckusick 			;
14841475Smckusick 		checksum = 0;
14941475Smckusick 		count = 0;
15041475Smckusick 		xmitcsum = 1;
15141475Smckusick 
15241475Smckusick 		/* now, read until a # or end of buffer is found */
15341475Smckusick 		while (count < BUFMAX) {
15441475Smckusick 			ch = GETC;
15541475Smckusick 			if (ch == '#')
15641475Smckusick 				break;
15741475Smckusick 			checksum = checksum + ch;
15841475Smckusick 			buffer[count] = ch;
15941475Smckusick 			count = count + 1;
16041475Smckusick 		}
16141475Smckusick 		buffer[count] = 0;
16241475Smckusick 
16341475Smckusick 		if (ch == '#') {
16441475Smckusick 			xmitcsum = hex(GETC) << 4;
16541475Smckusick 			xmitcsum += hex(GETC);
16641475Smckusick 			if (kgdb_debug && (checksum != xmitcsum)) {
16741475Smckusick 				printf(
16841475Smckusick 			"bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
16941475Smckusick 					checksum, xmitcsum, buffer);
17041475Smckusick 			}
17142367Smckusick 			if (checksum != xmitcsum) {
17241475Smckusick 				PUTC('-');	/* failed checksum */
17342367Smckusick 			} else {
17441475Smckusick 				PUTC('+');	/* successful transfer */
17541475Smckusick 				/*
17641475Smckusick 				 * if a sequence char is present, reply the
17741475Smckusick 				 * sequence ID
17841475Smckusick 				 */
17941475Smckusick 				if (buffer[2] == ':') {
18041475Smckusick 					PUTC(buffer[0]);
18141475Smckusick 					PUTC(buffer[1]);
18241475Smckusick 					/* remove sequence chars from buffer */
18341475Smckusick 					for (i = 3; i <= count; ++i)
18441475Smckusick 						buffer[i - 3] = buffer[i];
18541475Smckusick 				}
18641475Smckusick 			}
18741475Smckusick 		}
18841475Smckusick 	} while (checksum != xmitcsum);
18941475Smckusick }
19041475Smckusick 
19141475Smckusick /*
19241475Smckusick  * send the packet in buffer.  The host gets one chance to read it.  This
19341475Smckusick  * routine does not wait for a positive acknowledge.
19441475Smckusick  */
19541475Smckusick static void
19641475Smckusick putpacket(char *buffer)
19741475Smckusick {
19841475Smckusick 	unsigned char checksum;
19941475Smckusick 	int count;
20041475Smckusick 	char ch;
20141475Smckusick 
20241475Smckusick 	/* $<packet info>#<checksum>. */
20341475Smckusick 	do {
20441475Smckusick 		PUTC('$');
20541475Smckusick 		checksum = 0;
20641475Smckusick 		count = 0;
20741475Smckusick 
20841475Smckusick 		while (ch = buffer[count]) {
20941475Smckusick 			PUTC(ch);
21041475Smckusick 			checksum += ch;
21141475Smckusick 			count += 1;
21241475Smckusick 		}
21341475Smckusick 		PUTC('#');
21441475Smckusick 		PUTC(hexchars[checksum >> 4]);
21541475Smckusick 		PUTC(hexchars[checksum & 15]);
21641475Smckusick 
21741475Smckusick 	} while (0);	/* (GETC != '+'); */
21841475Smckusick 
21941475Smckusick }
22041475Smckusick 
22141475Smckusick static inline void
22241475Smckusick debug_error(char *format, char *parm)
22341475Smckusick {
22441475Smckusick 	if (kgdb_debug)
22541475Smckusick 		printf(format, parm);
22641475Smckusick }
22741475Smckusick 
22841475Smckusick /*
22941475Smckusick  * Convert at most 'dig' digits of hex data in buf into a value.
23041475Smckusick  * Stop on non-hex char.  Return a pointer to next char in buf.
23141475Smckusick  */
23241475Smckusick static char *
23341475Smckusick hex2val(char *buf, int *val, int dig)
23441475Smckusick {
23541475Smckusick 	int i, v;
23641475Smckusick 	char ch;
23741475Smckusick 
23841475Smckusick 	v = 0;
23941475Smckusick 	for (i = dig; --i >= 0; ) {
24041475Smckusick 		ch = *buf++;
24141475Smckusick 		if ((ch >= '0') && (ch <= '9'))
24241475Smckusick 			v = (v << 4) | (ch - '0');
24341475Smckusick 		else if ((ch >= 'a') && (ch <= 'f'))
24441475Smckusick 			v = (v << 4) | (ch - ('a' - 10));
24541475Smckusick 		else {
24641475Smckusick 			--buf;
24741475Smckusick 			break;
24841475Smckusick 		}
24941475Smckusick 	}
25041475Smckusick 	*val = v;
25141475Smckusick 	return (buf);
25241475Smckusick }
25341475Smckusick 
25441475Smckusick /*
25541475Smckusick  * convert the integer value 'val' into 'dig' hex digits, placing
25641475Smckusick  * result in buf.  Return a pointer to the last char put in buf (null).
25741475Smckusick  */
25841475Smckusick static char *
25941475Smckusick val2hex(char *buf, int val, int dig)
26041475Smckusick {
26141475Smckusick 	for (dig <<= 2; (dig -= 4) >= 0; )
26241475Smckusick 		*buf++ = hexchars[(val >> dig) & 0xf];
26341475Smckusick 	*buf = 0;
26441475Smckusick 	return (buf);
26541475Smckusick }
26641475Smckusick 
26741475Smckusick /*
26841475Smckusick  * convert the memory pointed to by mem into hex, placing result in buf.
26941475Smckusick  * return a pointer to the last char put in buf (null).
27041475Smckusick  */
27141475Smckusick static char *
27241475Smckusick mem2hex(char *buf, char *mem, int count)
27341475Smckusick {
27441475Smckusick 	if ((count & 1) || ((int)mem & 1)) {
27541475Smckusick 		char ch;
27641475Smckusick 
27741475Smckusick 		while(--count >= 0) {
27841475Smckusick 			ch = *mem++;
27941475Smckusick 			*buf++ = hexchars[ch >> 4];
28041475Smckusick 			*buf++ = hexchars[ch & 15];
28141475Smckusick 		}
28241475Smckusick 	} else {
28341475Smckusick 		u_short s;
28441475Smckusick 		u_short *mp = (u_short *)mem;
28541475Smckusick 
28641475Smckusick 		for (count >>= 1; --count >= 0; ) {
28741475Smckusick 			s = *mp++;
28841475Smckusick 			*buf++ = hexchars[(s >> 12) & 15];
28941475Smckusick 			*buf++ = hexchars[(s >> 8) & 15];
29041475Smckusick 			*buf++ = hexchars[(s >> 4) & 15];
29141475Smckusick 			*buf++ = hexchars[s & 15];
29241475Smckusick 		}
29341475Smckusick 	}
29441475Smckusick 	*buf = 0;
29541475Smckusick 	return (buf);
29641475Smckusick }
29741475Smckusick 
29841475Smckusick /*
29941475Smckusick  * Convert the hex array pointed to by buf into binary to be placed in mem.
30041475Smckusick  * Return a pointer to next char in buf.
30141475Smckusick  */
30241475Smckusick static char *
30341475Smckusick hex2mem(char *buf, char *mem, int count)
30441475Smckusick {
30541475Smckusick 	int i;
30641475Smckusick 	unsigned char ch;
30741475Smckusick 
30841475Smckusick 	for (i = 0; i < count; ++i) {
30941475Smckusick 		ch = hex(*buf++) << 4;
31041475Smckusick 		ch = ch + hex(*buf++);
31141475Smckusick 		*mem++ = ch;
31241475Smckusick 	}
31341475Smckusick 	return (buf);
31441475Smckusick }
31541475Smckusick 
31641475Smckusick /*
31741475Smckusick  * Translate a trap number into a unix compatible signal value.
31841475Smckusick  * (gdb only understands unix signal numbers).
31941475Smckusick  */
32041475Smckusick static int
32141475Smckusick computeSignal(int type)
32241475Smckusick {
32341475Smckusick 	int sigval;
32441475Smckusick 
32541475Smckusick 	switch (type &~ USER) {
32641475Smckusick 	case T_BUSERR:
32741475Smckusick 		sigval = SIGBUS;
32841475Smckusick 		break;		/* bus error           */
32941475Smckusick 	case T_ADDRERR:
33041475Smckusick 		sigval = SIGBUS;
33141475Smckusick 		break;		/* address error       */
33241475Smckusick 	case T_ILLINST:
33341475Smckusick 		sigval = SIGILL;
33441475Smckusick 		break;		/* illegal instruction */
33541475Smckusick 	case T_ZERODIV:
33641475Smckusick 		sigval = SIGFPE;
33741475Smckusick 		break;		/* zero divide         */
33841475Smckusick 	case T_CHKINST:
33941475Smckusick 		sigval = SIGFPE;
34041475Smckusick 		break;		/* chk instruction     */
34141475Smckusick 	case T_TRAPVINST:
34241475Smckusick 		sigval = SIGFPE;
34341475Smckusick 		break;		/* trapv instruction   */
34441475Smckusick 	case T_PRIVINST:
34541475Smckusick 		sigval = SIGILL;
34641475Smckusick 		break;		/* privilege violation */
34741475Smckusick 	case T_TRACE:
34841475Smckusick 		sigval = SIGTRAP;
34941475Smckusick 		break;		/* trace trap          */
35041475Smckusick 	case T_MMUFLT:
35141475Smckusick 		sigval = SIGSEGV;
35241475Smckusick 		break;
35341475Smckusick 	case T_SSIR:
35441475Smckusick 		sigval = SIGSEGV;
35541475Smckusick 		break;
35641475Smckusick 	case T_FMTERR:
35741475Smckusick 		sigval = SIGILL;
35841475Smckusick 		break;
35941475Smckusick 	case T_FPERR:
36041475Smckusick 		sigval = SIGFPE;
36141475Smckusick 		break;
36241475Smckusick 	case T_COPERR:
36341475Smckusick 		sigval = SIGFPE;
36441475Smckusick 		break;
365*43413Shibler 	case T_ASTFLT:
36641475Smckusick 		sigval = SIGINT;
36741475Smckusick 		break;
36841475Smckusick 	case T_TRAP15:
36941475Smckusick 		sigval = SIGIOT;
37041475Smckusick 		break;
37141475Smckusick 	default:
37241475Smckusick 		sigval = SIGEMT;
37341475Smckusick 		break;
37441475Smckusick 	}
37541475Smckusick 	return (sigval);
37641475Smckusick }
37741475Smckusick 
37841475Smckusick #define RESPOND(str) (bcopy(str, outbuffer, sizeof(str)))
37941475Smckusick 
38041475Smckusick /*
38141475Smckusick  * This function does all command procesing for interfacing to
38241475Smckusick  * a remote gdb.
38341475Smckusick  */
38441475Smckusick int
38541475Smckusick kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame)
38641475Smckusick {
38741475Smckusick 	int sigval;
38841475Smckusick 	int addr, length;
38941475Smckusick 	char *ptr;
39041475Smckusick 
39141475Smckusick 	if (kgdb_dev < 0)
39241475Smckusick 		/* not debugging */
39341475Smckusick 		return (0);
39441475Smckusick 
39541475Smckusick 	if (kgdb_debug)
39641475Smckusick 		printf("type=%d, code=%d, vector=0x%x, pc=0x%x, sr=0x%x\n",
39741475Smckusick 			type, code, frame->f_vector, frame->f_pc, frame->f_sr);
39841475Smckusick 
39941475Smckusick 	/* reply to host that an exception has occurred */
40041475Smckusick 	sigval = computeSignal(type);
40141475Smckusick 	outbuffer[0] = 'S';
40241475Smckusick 	(void)val2hex(&outbuffer[1], sigval, 2);
40341475Smckusick 	putpacket(outbuffer);
40441475Smckusick 
40541475Smckusick 	while (1) {
40641475Smckusick 		outbuffer[0] = 0;
40741475Smckusick 		getpacket(inbuffer);
40841475Smckusick 		ptr = inbuffer;
40941475Smckusick 		switch (*ptr++) {
41041475Smckusick 		case '?':
41141475Smckusick 			outbuffer[0] = 'S';
41241475Smckusick 			(void)val2hex(&outbuffer[1], sigval, 2);
41341475Smckusick 			break;
41441475Smckusick 		case 'g':	/* return the value of the CPU registers */
41541475Smckusick 			ptr = outbuffer;
41641475Smckusick 			if (type & USER)
41741475Smckusick 				ptr = mem2hex(ptr, (char *)frame->f_regs,
41841475Smckusick 					      sizeof(frame->f_regs));
41941475Smckusick 			else {
42041475Smckusick 				ptr = mem2hex(ptr, (char *)frame->f_regs,
42141475Smckusick 					      sizeof(frame->f_regs) - 4);
42241475Smckusick 				addr = (int)&frame->f_pc -
42341475Smckusick 					frame_bytes[frame->f_format];
42441475Smckusick 				ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
42541475Smckusick 			}
42641475Smckusick 			addr = frame->f_sr;
42741475Smckusick 			ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
42841475Smckusick 			ptr = mem2hex(ptr, (char *)&frame->f_pc,
42941475Smckusick 				      sizeof(frame->f_pc));
43041475Smckusick 			break;
43141475Smckusick 		case 'G':	/* set the value of the CPU registers */
43241475Smckusick 			ptr = hex2mem(ptr, (char *)frame->f_regs,
43341475Smckusick 				      sizeof(frame->f_regs) - 4);
43441475Smckusick 			ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
43541475Smckusick 			ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
43641475Smckusick 			frame->f_sr = addr;
43741475Smckusick 			ptr = hex2mem(ptr, (char *)&frame->f_pc,
43841475Smckusick 				      sizeof(frame->f_pc));
43941475Smckusick 			RESPOND("OK");
44041475Smckusick 			break;
44141475Smckusick 
44241475Smckusick 			/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
44341475Smckusick 		case 'm':
44441475Smckusick 			ptr = hex2val(ptr, &addr, 8);
44541475Smckusick 			if (*ptr++ != ',') {
44641475Smckusick 				RESPOND("E01");
44741475Smckusick 				debug_error("malformed read memory cmd: %s\n",
44841475Smckusick 					    inbuffer);
44941475Smckusick 				break;
45041475Smckusick 			}
45141475Smckusick 			ptr = hex2val(ptr, &length, 8);
45241475Smckusick 			if (length <= 0 || length >= BUFMAX*2) {
45341475Smckusick 				RESPOND("E02");
45441475Smckusick 				if (kgdb_debug)
45541475Smckusick 					printf("bad read memory length: %d\n",
45641475Smckusick 					       length);
45741475Smckusick 				break;
45841475Smckusick 			}
45941475Smckusick 			if (! kernacc(addr, length, B_READ)) {
46041475Smckusick 				RESPOND("E03");
46141475Smckusick 				if (kgdb_debug)
46241475Smckusick 					printf("read access violation addr 0x%x len %d\n", addr, length);
46341475Smckusick 				break;
46441475Smckusick 			}
46541475Smckusick 			(void)mem2hex(outbuffer, (char *)addr, length);
46641475Smckusick 			break;
46741475Smckusick 
46841475Smckusick 			/*
46941475Smckusick 			 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
47041475Smckusick 			 * return OK
47141475Smckusick 			 */
47241475Smckusick 		case 'M':
47341475Smckusick 			ptr = hex2val(ptr, &addr, 8);
47441475Smckusick 			if (*ptr++ != ',') {
47541475Smckusick 				RESPOND("E01");
47641475Smckusick 				debug_error("malformed write memory cmd: %s\n",
47741475Smckusick 					    inbuffer);
47841475Smckusick 				break;
47941475Smckusick 			}
48041475Smckusick 			ptr = hex2val(ptr, &length, 8);
48141475Smckusick 			if (*ptr++ != ':') {
48241475Smckusick 				RESPOND("E01");
48341475Smckusick 				debug_error("malformed write memory cmd: %s\n",
48441475Smckusick 					    inbuffer);
48541475Smckusick 				break;
48641475Smckusick 			}
48741475Smckusick 			if (length <= 0 || length >= BUFMAX*2 - 32) {
48841475Smckusick 				RESPOND("E02");
48941475Smckusick 				if (kgdb_debug)
49041475Smckusick 					printf("bad write memory length: %d\n",
49141475Smckusick 					       length);
49241475Smckusick 				break;
49341475Smckusick 			}
49441475Smckusick 			if (! kernacc(addr, length, B_READ)) {
49541475Smckusick 				RESPOND("E03");
49641475Smckusick 				if (kgdb_debug)
49741475Smckusick 					printf("write access violation addr 0x%x len %d\n", addr, length);
49841475Smckusick 				break;
49941475Smckusick 			}
50041475Smckusick 			if (! kernacc(addr, length, B_WRITE))
50141475Smckusick 				chgkprot(addr, length, B_WRITE);
50241475Smckusick 			(void)hex2mem(ptr, (char *)addr, length);
50341475Smckusick 			RESPOND("OK");
50441475Smckusick 			break;
50541475Smckusick 
50641475Smckusick 			/*
50741475Smckusick 			 * cAA..AA  Continue at address AA..AA
50841475Smckusick 			 * sAA..AA  Step one instruction from AA..AA
50941475Smckusick 			 * (addresses optional)
51041475Smckusick 			 */
51141475Smckusick 		case 'c':
51241475Smckusick 		case 's':
51341475Smckusick 			/*
51441475Smckusick 			 * try to read optional start address.
51541475Smckusick 			 */
51641475Smckusick 			if (ptr != hex2val(ptr, &addr, 8)) {
51741475Smckusick 				frame->f_pc = addr;
51841475Smckusick 				if (kgdb_debug)
51941475Smckusick 					printf("new pc = 0x%x\n", addr);
52041475Smckusick 			}
52141475Smckusick 			/* deal with the trace bit */
52241475Smckusick 			if (inbuffer[0] == 's')
52341475Smckusick 				frame->f_sr |= PSL_T;
52441475Smckusick 			else
52541475Smckusick 				frame->f_sr &=~ PSL_T;
52641475Smckusick 
52741475Smckusick 			if (kgdb_debug)
52841475Smckusick 				printf("restarting at 0x%x\n", frame->f_pc);
52941475Smckusick 
53041475Smckusick 			return (1);
53141475Smckusick 
53241475Smckusick 			/* kill the program (same as continue for now) */
53341475Smckusick 		case 'k':
53441475Smckusick 			return (1);
53541475Smckusick 		}
53641475Smckusick 		/* reply to the request */
53741475Smckusick 		putpacket(outbuffer);
53841475Smckusick 	}
53941475Smckusick }
54041475Smckusick #endif
541