xref: /dflybsd-src/contrib/gdb-7/gdb/stubs/sparc-stub.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
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 SPARC by Stu Grossman, Cygnus Support.
33*ef5ccd6cSJohn Marino  *
34*ef5ccd6cSJohn Marino  *  This code has been extensively tested on the Fujitsu SPARClite demo board.
35*ef5ccd6cSJohn Marino  *
36*ef5ccd6cSJohn Marino  *  To enable debugger support, two things need to happen.  One, a
37*ef5ccd6cSJohn Marino  *  call to set_debug_traps() is necessary in order to allow any breakpoints
38*ef5ccd6cSJohn Marino  *  or error conditions to be properly intercepted and reported to gdb.
39*ef5ccd6cSJohn Marino  *  Two, a breakpoint needs to be generated to begin communication.  This
40*ef5ccd6cSJohn Marino  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
41*ef5ccd6cSJohn Marino  *  simulates a breakpoint by executing a trap #1.
42*ef5ccd6cSJohn Marino  *
43*ef5ccd6cSJohn Marino  *************
44*ef5ccd6cSJohn Marino  *
45*ef5ccd6cSJohn Marino  *    The following gdb commands are supported:
46*ef5ccd6cSJohn Marino  *
47*ef5ccd6cSJohn Marino  * command          function                               Return value
48*ef5ccd6cSJohn Marino  *
49*ef5ccd6cSJohn Marino  *    g             return the value of the CPU registers  hex data or ENN
50*ef5ccd6cSJohn Marino  *    G             set the value of the CPU registers     OK or ENN
51*ef5ccd6cSJohn Marino  *
52*ef5ccd6cSJohn Marino  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
53*ef5ccd6cSJohn Marino  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
54*ef5ccd6cSJohn Marino  *
55*ef5ccd6cSJohn Marino  *    c             Resume at current address              SNN   ( signal NN)
56*ef5ccd6cSJohn Marino  *    cAA..AA       Continue at address AA..AA             SNN
57*ef5ccd6cSJohn Marino  *
58*ef5ccd6cSJohn Marino  *    s             Step one instruction                   SNN
59*ef5ccd6cSJohn Marino  *    sAA..AA       Step one instruction from AA..AA       SNN
60*ef5ccd6cSJohn Marino  *
61*ef5ccd6cSJohn Marino  *    k             kill
62*ef5ccd6cSJohn Marino  *
63*ef5ccd6cSJohn Marino  *    ?             What was the last sigval ?             SNN   (signal NN)
64*ef5ccd6cSJohn Marino  *
65*ef5ccd6cSJohn Marino  * All commands and responses are sent with a packet which includes a
66*ef5ccd6cSJohn Marino  * checksum.  A packet consists of
67*ef5ccd6cSJohn Marino  *
68*ef5ccd6cSJohn Marino  * $<packet info>#<checksum>.
69*ef5ccd6cSJohn Marino  *
70*ef5ccd6cSJohn Marino  * where
71*ef5ccd6cSJohn Marino  * <packet info> :: <characters representing the command or response>
72*ef5ccd6cSJohn Marino  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
73*ef5ccd6cSJohn Marino  *
74*ef5ccd6cSJohn Marino  * When a packet is received, it is first acknowledged with either '+' or '-'.
75*ef5ccd6cSJohn Marino  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
76*ef5ccd6cSJohn Marino  *
77*ef5ccd6cSJohn Marino  * Example:
78*ef5ccd6cSJohn Marino  *
79*ef5ccd6cSJohn Marino  * Host:                  Reply:
80*ef5ccd6cSJohn Marino  * $m0,10#2a               +$00010203040506070809101112131415#42
81*ef5ccd6cSJohn Marino  *
82*ef5ccd6cSJohn Marino  ****************************************************************************/
83*ef5ccd6cSJohn Marino 
84*ef5ccd6cSJohn Marino #include <string.h>
85*ef5ccd6cSJohn Marino #include <signal.h>
86*ef5ccd6cSJohn Marino 
87*ef5ccd6cSJohn Marino /************************************************************************
88*ef5ccd6cSJohn Marino  *
89*ef5ccd6cSJohn Marino  * external low-level support routines
90*ef5ccd6cSJohn Marino  */
91*ef5ccd6cSJohn Marino 
92*ef5ccd6cSJohn Marino extern void putDebugChar();	/* write a single character      */
93*ef5ccd6cSJohn Marino extern int getDebugChar();	/* read and return a single char */
94*ef5ccd6cSJohn Marino 
95*ef5ccd6cSJohn Marino /************************************************************************/
96*ef5ccd6cSJohn Marino /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
97*ef5ccd6cSJohn Marino /* at least NUMREGBYTES*2 are needed for register packets */
98*ef5ccd6cSJohn Marino #define BUFMAX 2048
99*ef5ccd6cSJohn Marino 
100*ef5ccd6cSJohn Marino static int initialized = 0;	/* !0 means we've been initialized */
101*ef5ccd6cSJohn Marino 
102*ef5ccd6cSJohn Marino static void set_mem_fault_trap();
103*ef5ccd6cSJohn Marino 
104*ef5ccd6cSJohn Marino static const char hexchars[]="0123456789abcdef";
105*ef5ccd6cSJohn Marino 
106*ef5ccd6cSJohn Marino #define NUMREGS 72
107*ef5ccd6cSJohn Marino 
108*ef5ccd6cSJohn Marino /* Number of bytes of registers.  */
109*ef5ccd6cSJohn Marino #define NUMREGBYTES (NUMREGS * 4)
110*ef5ccd6cSJohn Marino enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
111*ef5ccd6cSJohn Marino 		 O0, O1, O2, O3, O4, O5, SP, O7,
112*ef5ccd6cSJohn Marino 		 L0, L1, L2, L3, L4, L5, L6, L7,
113*ef5ccd6cSJohn Marino 		 I0, I1, I2, I3, I4, I5, FP, I7,
114*ef5ccd6cSJohn Marino 
115*ef5ccd6cSJohn Marino 		 F0, F1, F2, F3, F4, F5, F6, F7,
116*ef5ccd6cSJohn Marino 		 F8, F9, F10, F11, F12, F13, F14, F15,
117*ef5ccd6cSJohn Marino 		 F16, F17, F18, F19, F20, F21, F22, F23,
118*ef5ccd6cSJohn Marino 		 F24, F25, F26, F27, F28, F29, F30, F31,
119*ef5ccd6cSJohn Marino 		 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
120*ef5ccd6cSJohn Marino 
121*ef5ccd6cSJohn Marino /***************************  ASSEMBLY CODE MACROS *************************/
122*ef5ccd6cSJohn Marino /* 									   */
123*ef5ccd6cSJohn Marino 
124*ef5ccd6cSJohn Marino extern void trap_low();
125*ef5ccd6cSJohn Marino 
126*ef5ccd6cSJohn Marino asm("
127*ef5ccd6cSJohn Marino 	.reserve trapstack, 1000 * 4, \"bss\", 8
128*ef5ccd6cSJohn Marino 
129*ef5ccd6cSJohn Marino 	.data
130*ef5ccd6cSJohn Marino 	.align	4
131*ef5ccd6cSJohn Marino 
132*ef5ccd6cSJohn Marino in_trap_handler:
133*ef5ccd6cSJohn Marino 	.word	0
134*ef5ccd6cSJohn Marino 
135*ef5ccd6cSJohn Marino 	.text
136*ef5ccd6cSJohn Marino 	.align 4
137*ef5ccd6cSJohn Marino 
138*ef5ccd6cSJohn Marino ! This function is called when any SPARC trap (except window overflow or
139*ef5ccd6cSJohn Marino ! underflow) occurs.  It makes sure that the invalid register window is still
140*ef5ccd6cSJohn Marino ! available before jumping into C code.  It will also restore the world if you
141*ef5ccd6cSJohn Marino ! return from handle_exception.
142*ef5ccd6cSJohn Marino 
143*ef5ccd6cSJohn Marino 	.globl _trap_low
144*ef5ccd6cSJohn Marino _trap_low:
145*ef5ccd6cSJohn Marino 	mov	%psr, %l0
146*ef5ccd6cSJohn Marino 	mov	%wim, %l3
147*ef5ccd6cSJohn Marino 
148*ef5ccd6cSJohn Marino 	srl	%l3, %l0, %l4		! wim >> cwp
149*ef5ccd6cSJohn Marino 	cmp	%l4, 1
150*ef5ccd6cSJohn Marino 	bne	window_fine		! Branch if not in the invalid window
151*ef5ccd6cSJohn Marino 	nop
152*ef5ccd6cSJohn Marino 
153*ef5ccd6cSJohn Marino ! Handle window overflow
154*ef5ccd6cSJohn Marino 
155*ef5ccd6cSJohn Marino 	mov	%g1, %l4		! Save g1, we use it to hold the wim
156*ef5ccd6cSJohn Marino 	srl	%l3, 1, %g1		! Rotate wim right
157*ef5ccd6cSJohn Marino 	tst	%g1
158*ef5ccd6cSJohn Marino 	bg	good_wim		! Branch if new wim is non-zero
159*ef5ccd6cSJohn Marino 	nop
160*ef5ccd6cSJohn Marino 
161*ef5ccd6cSJohn Marino ! At this point, we need to bring a 1 into the high order bit of the wim.
162*ef5ccd6cSJohn Marino ! Since we don't want to make any assumptions about the number of register
163*ef5ccd6cSJohn Marino ! windows, we figure it out dynamically so as to setup the wim correctly.
164*ef5ccd6cSJohn Marino 
165*ef5ccd6cSJohn Marino 	not	%g1			! Fill g1 with ones
166*ef5ccd6cSJohn Marino 	mov	%g1, %wim		! Fill the wim with ones
167*ef5ccd6cSJohn Marino 	nop
168*ef5ccd6cSJohn Marino 	nop
169*ef5ccd6cSJohn Marino 	nop
170*ef5ccd6cSJohn Marino 	mov	%wim, %g1		! Read back the wim
171*ef5ccd6cSJohn Marino 	inc	%g1			! Now g1 has 1 just to left of wim
172*ef5ccd6cSJohn Marino 	srl	%g1, 1, %g1		! Now put 1 at top of wim
173*ef5ccd6cSJohn Marino 	mov	%g0, %wim		! Clear wim so that subsequent save
174*ef5ccd6cSJohn Marino 	nop				!  won't trap
175*ef5ccd6cSJohn Marino 	nop
176*ef5ccd6cSJohn Marino 	nop
177*ef5ccd6cSJohn Marino 
178*ef5ccd6cSJohn Marino good_wim:
179*ef5ccd6cSJohn Marino 	save	%g0, %g0, %g0		! Slip into next window
180*ef5ccd6cSJohn Marino 	mov	%g1, %wim		! Install the new wim
181*ef5ccd6cSJohn Marino 
182*ef5ccd6cSJohn Marino 	std	%l0, [%sp + 0 * 4]	! save L & I registers
183*ef5ccd6cSJohn Marino 	std	%l2, [%sp + 2 * 4]
184*ef5ccd6cSJohn Marino 	std	%l4, [%sp + 4 * 4]
185*ef5ccd6cSJohn Marino 	std	%l6, [%sp + 6 * 4]
186*ef5ccd6cSJohn Marino 
187*ef5ccd6cSJohn Marino 	std	%i0, [%sp + 8 * 4]
188*ef5ccd6cSJohn Marino 	std	%i2, [%sp + 10 * 4]
189*ef5ccd6cSJohn Marino 	std	%i4, [%sp + 12 * 4]
190*ef5ccd6cSJohn Marino 	std	%i6, [%sp + 14 * 4]
191*ef5ccd6cSJohn Marino 
192*ef5ccd6cSJohn Marino 	restore				! Go back to trap window.
193*ef5ccd6cSJohn Marino 	mov	%l4, %g1		! Restore %g1
194*ef5ccd6cSJohn Marino 
195*ef5ccd6cSJohn Marino window_fine:
196*ef5ccd6cSJohn Marino 	sethi	%hi(in_trap_handler), %l4
197*ef5ccd6cSJohn Marino 	ld	[%lo(in_trap_handler) + %l4], %l5
198*ef5ccd6cSJohn Marino 	tst	%l5
199*ef5ccd6cSJohn Marino 	bg	recursive_trap
200*ef5ccd6cSJohn Marino 	inc	%l5
201*ef5ccd6cSJohn Marino 
202*ef5ccd6cSJohn Marino 	set	trapstack+1000*4, %sp	! Switch to trap stack
203*ef5ccd6cSJohn Marino 
204*ef5ccd6cSJohn Marino recursive_trap:
205*ef5ccd6cSJohn Marino 	st	%l5, [%lo(in_trap_handler) + %l4]
206*ef5ccd6cSJohn Marino 	sub	%sp,(16+1+6+1+72)*4,%sp	! Make room for input & locals
207*ef5ccd6cSJohn Marino  					! + hidden arg + arg spill
208*ef5ccd6cSJohn Marino 					! + doubleword alignment
209*ef5ccd6cSJohn Marino 					! + registers[72] local var
210*ef5ccd6cSJohn Marino 
211*ef5ccd6cSJohn Marino 	std	%g0, [%sp + (24 + 0) * 4] ! registers[Gx]
212*ef5ccd6cSJohn Marino 	std	%g2, [%sp + (24 + 2) * 4]
213*ef5ccd6cSJohn Marino 	std	%g4, [%sp + (24 + 4) * 4]
214*ef5ccd6cSJohn Marino 	std	%g6, [%sp + (24 + 6) * 4]
215*ef5ccd6cSJohn Marino 
216*ef5ccd6cSJohn Marino 	std	%i0, [%sp + (24 + 8) * 4] ! registers[Ox]
217*ef5ccd6cSJohn Marino 	std	%i2, [%sp + (24 + 10) * 4]
218*ef5ccd6cSJohn Marino 	std	%i4, [%sp + (24 + 12) * 4]
219*ef5ccd6cSJohn Marino 	std	%i6, [%sp + (24 + 14) * 4]
220*ef5ccd6cSJohn Marino 					! F0->F31 not implemented
221*ef5ccd6cSJohn Marino 	mov	%y, %l4
222*ef5ccd6cSJohn Marino 	mov	%tbr, %l5
223*ef5ccd6cSJohn Marino 	st	%l4, [%sp + (24 + 64) * 4] ! Y
224*ef5ccd6cSJohn Marino 	st	%l0, [%sp + (24 + 65) * 4] ! PSR
225*ef5ccd6cSJohn Marino 	st	%l3, [%sp + (24 + 66) * 4] ! WIM
226*ef5ccd6cSJohn Marino 	st	%l5, [%sp + (24 + 67) * 4] ! TBR
227*ef5ccd6cSJohn Marino 	st	%l1, [%sp + (24 + 68) * 4] ! PC
228*ef5ccd6cSJohn Marino 	st	%l2, [%sp + (24 + 69) * 4] ! NPC
229*ef5ccd6cSJohn Marino 
230*ef5ccd6cSJohn Marino 					! CPSR and FPSR not impl
231*ef5ccd6cSJohn Marino 
232*ef5ccd6cSJohn Marino 	or	%l0, 0xf20, %l4
233*ef5ccd6cSJohn Marino 	mov	%l4, %psr		! Turn on traps, disable interrupts
234*ef5ccd6cSJohn Marino 
235*ef5ccd6cSJohn Marino 	call	_handle_exception
236*ef5ccd6cSJohn Marino 	add	%sp, 24 * 4, %o0	! Pass address of registers
237*ef5ccd6cSJohn Marino 
238*ef5ccd6cSJohn Marino ! Reload all of the registers that aren't on the stack
239*ef5ccd6cSJohn Marino 
240*ef5ccd6cSJohn Marino 	ld	[%sp + (24 + 1) * 4], %g1 ! registers[Gx]
241*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 2) * 4], %g2
242*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 4) * 4], %g4
243*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 6) * 4], %g6
244*ef5ccd6cSJohn Marino 
245*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 8) * 4], %i0 ! registers[Ox]
246*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 10) * 4], %i2
247*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 12) * 4], %i4
248*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 14) * 4], %i6
249*ef5ccd6cSJohn Marino 
250*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 64) * 4], %l0 ! Y & PSR
251*ef5ccd6cSJohn Marino 	ldd	[%sp + (24 + 68) * 4], %l2 ! PC & NPC
252*ef5ccd6cSJohn Marino 
253*ef5ccd6cSJohn Marino 	restore				! Ensure that previous window is valid
254*ef5ccd6cSJohn Marino 	save	%g0, %g0, %g0		!  by causing a window_underflow trap
255*ef5ccd6cSJohn Marino 
256*ef5ccd6cSJohn Marino 	mov	%l0, %y
257*ef5ccd6cSJohn Marino 	mov	%l1, %psr		! Make sure that traps are disabled
258*ef5ccd6cSJohn Marino 					! for rett
259*ef5ccd6cSJohn Marino 
260*ef5ccd6cSJohn Marino 	sethi	%hi(in_trap_handler), %l4
261*ef5ccd6cSJohn Marino 	ld	[%lo(in_trap_handler) + %l4], %l5
262*ef5ccd6cSJohn Marino 	dec	%l5
263*ef5ccd6cSJohn Marino 	st	%l5, [%lo(in_trap_handler) + %l4]
264*ef5ccd6cSJohn Marino 
265*ef5ccd6cSJohn Marino 	jmpl	%l2, %g0		! Restore old PC
266*ef5ccd6cSJohn Marino 	rett	%l3			! Restore old nPC
267*ef5ccd6cSJohn Marino ");
268*ef5ccd6cSJohn Marino 
269*ef5ccd6cSJohn Marino /* Convert ch from a hex digit to an int */
270*ef5ccd6cSJohn Marino 
271*ef5ccd6cSJohn Marino static int
hex(unsigned char ch)272*ef5ccd6cSJohn Marino hex (unsigned char ch)
273*ef5ccd6cSJohn Marino {
274*ef5ccd6cSJohn Marino   if (ch >= 'a' && ch <= 'f')
275*ef5ccd6cSJohn Marino     return ch-'a'+10;
276*ef5ccd6cSJohn Marino   if (ch >= '0' && ch <= '9')
277*ef5ccd6cSJohn Marino     return ch-'0';
278*ef5ccd6cSJohn Marino   if (ch >= 'A' && ch <= 'F')
279*ef5ccd6cSJohn Marino     return ch-'A'+10;
280*ef5ccd6cSJohn Marino   return -1;
281*ef5ccd6cSJohn Marino }
282*ef5ccd6cSJohn Marino 
283*ef5ccd6cSJohn Marino static char remcomInBuffer[BUFMAX];
284*ef5ccd6cSJohn Marino static char remcomOutBuffer[BUFMAX];
285*ef5ccd6cSJohn Marino 
286*ef5ccd6cSJohn Marino /* scan for the sequence $<data>#<checksum>     */
287*ef5ccd6cSJohn Marino 
288*ef5ccd6cSJohn Marino unsigned char *
getpacket(void)289*ef5ccd6cSJohn Marino getpacket (void)
290*ef5ccd6cSJohn Marino {
291*ef5ccd6cSJohn Marino   unsigned char *buffer = &remcomInBuffer[0];
292*ef5ccd6cSJohn Marino   unsigned char checksum;
293*ef5ccd6cSJohn Marino   unsigned char xmitcsum;
294*ef5ccd6cSJohn Marino   int count;
295*ef5ccd6cSJohn Marino   char ch;
296*ef5ccd6cSJohn Marino 
297*ef5ccd6cSJohn Marino   while (1)
298*ef5ccd6cSJohn Marino     {
299*ef5ccd6cSJohn Marino       /* wait around for the start character, ignore all other characters */
300*ef5ccd6cSJohn Marino       while ((ch = getDebugChar ()) != '$')
301*ef5ccd6cSJohn Marino 	;
302*ef5ccd6cSJohn Marino 
303*ef5ccd6cSJohn Marino retry:
304*ef5ccd6cSJohn Marino       checksum = 0;
305*ef5ccd6cSJohn Marino       xmitcsum = -1;
306*ef5ccd6cSJohn Marino       count = 0;
307*ef5ccd6cSJohn Marino 
308*ef5ccd6cSJohn Marino       /* now, read until a # or end of buffer is found */
309*ef5ccd6cSJohn Marino       while (count < BUFMAX - 1)
310*ef5ccd6cSJohn Marino 	{
311*ef5ccd6cSJohn Marino 	  ch = getDebugChar ();
312*ef5ccd6cSJohn Marino           if (ch == '$')
313*ef5ccd6cSJohn Marino             goto retry;
314*ef5ccd6cSJohn Marino 	  if (ch == '#')
315*ef5ccd6cSJohn Marino 	    break;
316*ef5ccd6cSJohn Marino 	  checksum = checksum + ch;
317*ef5ccd6cSJohn Marino 	  buffer[count] = ch;
318*ef5ccd6cSJohn Marino 	  count = count + 1;
319*ef5ccd6cSJohn Marino 	}
320*ef5ccd6cSJohn Marino       buffer[count] = 0;
321*ef5ccd6cSJohn Marino 
322*ef5ccd6cSJohn Marino       if (ch == '#')
323*ef5ccd6cSJohn Marino 	{
324*ef5ccd6cSJohn Marino 	  ch = getDebugChar ();
325*ef5ccd6cSJohn Marino 	  xmitcsum = hex (ch) << 4;
326*ef5ccd6cSJohn Marino 	  ch = getDebugChar ();
327*ef5ccd6cSJohn Marino 	  xmitcsum += hex (ch);
328*ef5ccd6cSJohn Marino 
329*ef5ccd6cSJohn Marino 	  if (checksum != xmitcsum)
330*ef5ccd6cSJohn Marino 	    {
331*ef5ccd6cSJohn Marino 	      putDebugChar ('-');	/* failed checksum */
332*ef5ccd6cSJohn Marino 	    }
333*ef5ccd6cSJohn Marino 	  else
334*ef5ccd6cSJohn Marino 	    {
335*ef5ccd6cSJohn Marino 	      putDebugChar ('+');	/* successful transfer */
336*ef5ccd6cSJohn Marino 
337*ef5ccd6cSJohn Marino 	      /* if a sequence char is present, reply the sequence ID */
338*ef5ccd6cSJohn Marino 	      if (buffer[2] == ':')
339*ef5ccd6cSJohn Marino 		{
340*ef5ccd6cSJohn Marino 		  putDebugChar (buffer[0]);
341*ef5ccd6cSJohn Marino 		  putDebugChar (buffer[1]);
342*ef5ccd6cSJohn Marino 
343*ef5ccd6cSJohn Marino 		  return &buffer[3];
344*ef5ccd6cSJohn Marino 		}
345*ef5ccd6cSJohn Marino 
346*ef5ccd6cSJohn Marino 	      return &buffer[0];
347*ef5ccd6cSJohn Marino 	    }
348*ef5ccd6cSJohn Marino 	}
349*ef5ccd6cSJohn Marino     }
350*ef5ccd6cSJohn Marino }
351*ef5ccd6cSJohn Marino 
352*ef5ccd6cSJohn Marino /* send the packet in buffer.  */
353*ef5ccd6cSJohn Marino 
354*ef5ccd6cSJohn Marino static void
putpacket(unsigned char * buffer)355*ef5ccd6cSJohn Marino putpacket (unsigned char *buffer)
356*ef5ccd6cSJohn Marino {
357*ef5ccd6cSJohn Marino   unsigned char checksum;
358*ef5ccd6cSJohn Marino   int count;
359*ef5ccd6cSJohn Marino   unsigned char ch;
360*ef5ccd6cSJohn Marino 
361*ef5ccd6cSJohn Marino   /*  $<packet info>#<checksum>. */
362*ef5ccd6cSJohn Marino   do
363*ef5ccd6cSJohn Marino     {
364*ef5ccd6cSJohn Marino       putDebugChar('$');
365*ef5ccd6cSJohn Marino       checksum = 0;
366*ef5ccd6cSJohn Marino       count = 0;
367*ef5ccd6cSJohn Marino 
368*ef5ccd6cSJohn Marino       while (ch = buffer[count])
369*ef5ccd6cSJohn Marino 	{
370*ef5ccd6cSJohn Marino 	  putDebugChar(ch);
371*ef5ccd6cSJohn Marino 	  checksum += ch;
372*ef5ccd6cSJohn Marino 	  count += 1;
373*ef5ccd6cSJohn Marino 	}
374*ef5ccd6cSJohn Marino 
375*ef5ccd6cSJohn Marino       putDebugChar('#');
376*ef5ccd6cSJohn Marino       putDebugChar(hexchars[checksum >> 4]);
377*ef5ccd6cSJohn Marino       putDebugChar(hexchars[checksum & 0xf]);
378*ef5ccd6cSJohn Marino 
379*ef5ccd6cSJohn Marino     }
380*ef5ccd6cSJohn Marino   while (getDebugChar() != '+');
381*ef5ccd6cSJohn Marino }
382*ef5ccd6cSJohn Marino 
383*ef5ccd6cSJohn Marino /* Indicate to caller of mem2hex or hex2mem that there has been an
384*ef5ccd6cSJohn Marino    error.  */
385*ef5ccd6cSJohn Marino static volatile int mem_err = 0;
386*ef5ccd6cSJohn Marino 
387*ef5ccd6cSJohn Marino /* Convert the memory pointed to by mem into hex, placing result in buf.
388*ef5ccd6cSJohn Marino  * Return a pointer to the last char put in buf (null), in case of mem fault,
389*ef5ccd6cSJohn Marino  * return 0.
390*ef5ccd6cSJohn Marino  * If MAY_FAULT is non-zero, then we will handle memory faults by returning
391*ef5ccd6cSJohn Marino  * a 0, else treat a fault like any other fault in the stub.
392*ef5ccd6cSJohn Marino  */
393*ef5ccd6cSJohn Marino 
394*ef5ccd6cSJohn Marino static unsigned char *
mem2hex(unsigned char * mem,unsigned char * buf,int count,int may_fault)395*ef5ccd6cSJohn Marino mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
396*ef5ccd6cSJohn Marino {
397*ef5ccd6cSJohn Marino   unsigned char ch;
398*ef5ccd6cSJohn Marino 
399*ef5ccd6cSJohn Marino   set_mem_fault_trap(may_fault);
400*ef5ccd6cSJohn Marino 
401*ef5ccd6cSJohn Marino   while (count-- > 0)
402*ef5ccd6cSJohn Marino     {
403*ef5ccd6cSJohn Marino       ch = *mem++;
404*ef5ccd6cSJohn Marino       if (mem_err)
405*ef5ccd6cSJohn Marino 	return 0;
406*ef5ccd6cSJohn Marino       *buf++ = hexchars[ch >> 4];
407*ef5ccd6cSJohn Marino       *buf++ = hexchars[ch & 0xf];
408*ef5ccd6cSJohn Marino     }
409*ef5ccd6cSJohn Marino 
410*ef5ccd6cSJohn Marino   *buf = 0;
411*ef5ccd6cSJohn Marino 
412*ef5ccd6cSJohn Marino   set_mem_fault_trap(0);
413*ef5ccd6cSJohn Marino 
414*ef5ccd6cSJohn Marino   return buf;
415*ef5ccd6cSJohn Marino }
416*ef5ccd6cSJohn Marino 
417*ef5ccd6cSJohn Marino /* convert the hex array pointed to by buf into binary to be placed in mem
418*ef5ccd6cSJohn Marino  * return a pointer to the character AFTER the last byte written */
419*ef5ccd6cSJohn Marino 
420*ef5ccd6cSJohn Marino static char *
hex2mem(unsigned char * buf,unsigned char * mem,int count,int may_fault)421*ef5ccd6cSJohn Marino hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
422*ef5ccd6cSJohn Marino {
423*ef5ccd6cSJohn Marino   int i;
424*ef5ccd6cSJohn Marino   unsigned char ch;
425*ef5ccd6cSJohn Marino 
426*ef5ccd6cSJohn Marino   set_mem_fault_trap(may_fault);
427*ef5ccd6cSJohn Marino 
428*ef5ccd6cSJohn Marino   for (i=0; i<count; i++)
429*ef5ccd6cSJohn Marino     {
430*ef5ccd6cSJohn Marino       ch = hex(*buf++) << 4;
431*ef5ccd6cSJohn Marino       ch |= hex(*buf++);
432*ef5ccd6cSJohn Marino       *mem++ = ch;
433*ef5ccd6cSJohn Marino       if (mem_err)
434*ef5ccd6cSJohn Marino 	return 0;
435*ef5ccd6cSJohn Marino     }
436*ef5ccd6cSJohn Marino 
437*ef5ccd6cSJohn Marino   set_mem_fault_trap(0);
438*ef5ccd6cSJohn Marino 
439*ef5ccd6cSJohn Marino   return mem;
440*ef5ccd6cSJohn Marino }
441*ef5ccd6cSJohn Marino 
442*ef5ccd6cSJohn Marino /* This table contains the mapping between SPARC hardware trap types, and
443*ef5ccd6cSJohn Marino    signals, which are primarily what GDB understands.  It also indicates
444*ef5ccd6cSJohn Marino    which hardware traps we need to commandeer when initializing the stub. */
445*ef5ccd6cSJohn Marino 
446*ef5ccd6cSJohn Marino static struct hard_trap_info
447*ef5ccd6cSJohn Marino {
448*ef5ccd6cSJohn Marino   unsigned char tt;		/* Trap type code for SPARClite */
449*ef5ccd6cSJohn Marino   unsigned char signo;		/* Signal that we map this trap into */
450*ef5ccd6cSJohn Marino } hard_trap_info[] = {
451*ef5ccd6cSJohn Marino   {1, SIGSEGV},			/* instruction access error */
452*ef5ccd6cSJohn Marino   {2, SIGILL},			/* privileged instruction */
453*ef5ccd6cSJohn Marino   {3, SIGILL},			/* illegal instruction */
454*ef5ccd6cSJohn Marino   {4, SIGEMT},			/* fp disabled */
455*ef5ccd6cSJohn Marino   {36, SIGEMT},			/* cp disabled */
456*ef5ccd6cSJohn Marino   {7, SIGBUS},			/* mem address not aligned */
457*ef5ccd6cSJohn Marino   {9, SIGSEGV},			/* data access exception */
458*ef5ccd6cSJohn Marino   {10, SIGEMT},			/* tag overflow */
459*ef5ccd6cSJohn Marino   {128+1, SIGTRAP},		/* ta 1 - normal breakpoint instruction */
460*ef5ccd6cSJohn Marino   {0, 0}			/* Must be last */
461*ef5ccd6cSJohn Marino };
462*ef5ccd6cSJohn Marino 
463*ef5ccd6cSJohn Marino /* Set up exception handlers for tracing and breakpoints */
464*ef5ccd6cSJohn Marino 
465*ef5ccd6cSJohn Marino void
set_debug_traps(void)466*ef5ccd6cSJohn Marino set_debug_traps (void)
467*ef5ccd6cSJohn Marino {
468*ef5ccd6cSJohn Marino   struct hard_trap_info *ht;
469*ef5ccd6cSJohn Marino 
470*ef5ccd6cSJohn Marino   for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
471*ef5ccd6cSJohn Marino     exceptionHandler(ht->tt, trap_low);
472*ef5ccd6cSJohn Marino 
473*ef5ccd6cSJohn Marino   initialized = 1;
474*ef5ccd6cSJohn Marino }
475*ef5ccd6cSJohn Marino 
476*ef5ccd6cSJohn Marino asm ("
477*ef5ccd6cSJohn Marino ! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
478*ef5ccd6cSJohn Marino ! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
479*ef5ccd6cSJohn Marino ! 0 would ever contain code that could mem fault.  This routine will skip
480*ef5ccd6cSJohn Marino ! past the faulting instruction after setting mem_err.
481*ef5ccd6cSJohn Marino 
482*ef5ccd6cSJohn Marino 	.text
483*ef5ccd6cSJohn Marino 	.align 4
484*ef5ccd6cSJohn Marino 
485*ef5ccd6cSJohn Marino _fltr_set_mem_err:
486*ef5ccd6cSJohn Marino 	sethi %hi(_mem_err), %l0
487*ef5ccd6cSJohn Marino 	st %l1, [%l0 + %lo(_mem_err)]
488*ef5ccd6cSJohn Marino 	jmpl %l2, %g0
489*ef5ccd6cSJohn Marino 	rett %l2+4
490*ef5ccd6cSJohn Marino ");
491*ef5ccd6cSJohn Marino 
492*ef5ccd6cSJohn Marino static void
set_mem_fault_trap(int enable)493*ef5ccd6cSJohn Marino set_mem_fault_trap (int enable)
494*ef5ccd6cSJohn Marino {
495*ef5ccd6cSJohn Marino   extern void fltr_set_mem_err();
496*ef5ccd6cSJohn Marino   mem_err = 0;
497*ef5ccd6cSJohn Marino 
498*ef5ccd6cSJohn Marino   if (enable)
499*ef5ccd6cSJohn Marino     exceptionHandler(9, fltr_set_mem_err);
500*ef5ccd6cSJohn Marino   else
501*ef5ccd6cSJohn Marino     exceptionHandler(9, trap_low);
502*ef5ccd6cSJohn Marino }
503*ef5ccd6cSJohn Marino 
504*ef5ccd6cSJohn Marino /* Convert the SPARC hardware trap type code to a unix signal number. */
505*ef5ccd6cSJohn Marino 
506*ef5ccd6cSJohn Marino static int
computeSignal(int tt)507*ef5ccd6cSJohn Marino computeSignal (int tt)
508*ef5ccd6cSJohn Marino {
509*ef5ccd6cSJohn Marino   struct hard_trap_info *ht;
510*ef5ccd6cSJohn Marino 
511*ef5ccd6cSJohn Marino   for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
512*ef5ccd6cSJohn Marino     if (ht->tt == tt)
513*ef5ccd6cSJohn Marino       return ht->signo;
514*ef5ccd6cSJohn Marino 
515*ef5ccd6cSJohn Marino   return SIGHUP;		/* default for things we don't know about */
516*ef5ccd6cSJohn Marino }
517*ef5ccd6cSJohn Marino 
518*ef5ccd6cSJohn Marino /*
519*ef5ccd6cSJohn Marino  * While we find nice hex chars, build an int.
520*ef5ccd6cSJohn Marino  * Return number of chars processed.
521*ef5ccd6cSJohn Marino  */
522*ef5ccd6cSJohn Marino 
523*ef5ccd6cSJohn Marino static int
hexToInt(char ** ptr,int * intValue)524*ef5ccd6cSJohn Marino hexToInt(char **ptr, int *intValue)
525*ef5ccd6cSJohn Marino {
526*ef5ccd6cSJohn Marino   int numChars = 0;
527*ef5ccd6cSJohn Marino   int hexValue;
528*ef5ccd6cSJohn Marino 
529*ef5ccd6cSJohn Marino   *intValue = 0;
530*ef5ccd6cSJohn Marino 
531*ef5ccd6cSJohn Marino   while (**ptr)
532*ef5ccd6cSJohn Marino     {
533*ef5ccd6cSJohn Marino       hexValue = hex(**ptr);
534*ef5ccd6cSJohn Marino       if (hexValue < 0)
535*ef5ccd6cSJohn Marino 	break;
536*ef5ccd6cSJohn Marino 
537*ef5ccd6cSJohn Marino       *intValue = (*intValue << 4) | hexValue;
538*ef5ccd6cSJohn Marino       numChars ++;
539*ef5ccd6cSJohn Marino 
540*ef5ccd6cSJohn Marino       (*ptr)++;
541*ef5ccd6cSJohn Marino     }
542*ef5ccd6cSJohn Marino 
543*ef5ccd6cSJohn Marino   return (numChars);
544*ef5ccd6cSJohn Marino }
545*ef5ccd6cSJohn Marino 
546*ef5ccd6cSJohn Marino /*
547*ef5ccd6cSJohn Marino  * This function does all command procesing for interfacing to gdb.  It
548*ef5ccd6cSJohn Marino  * returns 1 if you should skip the instruction at the trap address, 0
549*ef5ccd6cSJohn Marino  * otherwise.
550*ef5ccd6cSJohn Marino  */
551*ef5ccd6cSJohn Marino 
552*ef5ccd6cSJohn Marino extern void breakinst();
553*ef5ccd6cSJohn Marino 
554*ef5ccd6cSJohn Marino static void
handle_exception(unsigned long * registers)555*ef5ccd6cSJohn Marino handle_exception (unsigned long *registers)
556*ef5ccd6cSJohn Marino {
557*ef5ccd6cSJohn Marino   int tt;			/* Trap type */
558*ef5ccd6cSJohn Marino   int sigval;
559*ef5ccd6cSJohn Marino   int addr;
560*ef5ccd6cSJohn Marino   int length;
561*ef5ccd6cSJohn Marino   char *ptr;
562*ef5ccd6cSJohn Marino   unsigned long *sp;
563*ef5ccd6cSJohn Marino 
564*ef5ccd6cSJohn Marino /* First, we must force all of the windows to be spilled out */
565*ef5ccd6cSJohn Marino 
566*ef5ccd6cSJohn Marino   asm("	save %sp, -64, %sp
567*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
568*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
569*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
570*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
571*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
572*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
573*ef5ccd6cSJohn Marino 	save %sp, -64, %sp
574*ef5ccd6cSJohn Marino 	restore
575*ef5ccd6cSJohn Marino 	restore
576*ef5ccd6cSJohn Marino 	restore
577*ef5ccd6cSJohn Marino 	restore
578*ef5ccd6cSJohn Marino 	restore
579*ef5ccd6cSJohn Marino 	restore
580*ef5ccd6cSJohn Marino 	restore
581*ef5ccd6cSJohn Marino 	restore
582*ef5ccd6cSJohn Marino ");
583*ef5ccd6cSJohn Marino 
584*ef5ccd6cSJohn Marino   if (registers[PC] == (unsigned long)breakinst)
585*ef5ccd6cSJohn Marino     {
586*ef5ccd6cSJohn Marino       registers[PC] = registers[NPC];
587*ef5ccd6cSJohn Marino       registers[NPC] += 4;
588*ef5ccd6cSJohn Marino     }
589*ef5ccd6cSJohn Marino 
590*ef5ccd6cSJohn Marino   sp = (unsigned long *)registers[SP];
591*ef5ccd6cSJohn Marino 
592*ef5ccd6cSJohn Marino   tt = (registers[TBR] >> 4) & 0xff;
593*ef5ccd6cSJohn Marino 
594*ef5ccd6cSJohn Marino   /* reply to host that an exception has occurred */
595*ef5ccd6cSJohn Marino   sigval = computeSignal(tt);
596*ef5ccd6cSJohn Marino   ptr = remcomOutBuffer;
597*ef5ccd6cSJohn Marino 
598*ef5ccd6cSJohn Marino   *ptr++ = 'T';
599*ef5ccd6cSJohn Marino   *ptr++ = hexchars[sigval >> 4];
600*ef5ccd6cSJohn Marino   *ptr++ = hexchars[sigval & 0xf];
601*ef5ccd6cSJohn Marino 
602*ef5ccd6cSJohn Marino   *ptr++ = hexchars[PC >> 4];
603*ef5ccd6cSJohn Marino   *ptr++ = hexchars[PC & 0xf];
604*ef5ccd6cSJohn Marino   *ptr++ = ':';
605*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
606*ef5ccd6cSJohn Marino   *ptr++ = ';';
607*ef5ccd6cSJohn Marino 
608*ef5ccd6cSJohn Marino   *ptr++ = hexchars[FP >> 4];
609*ef5ccd6cSJohn Marino   *ptr++ = hexchars[FP & 0xf];
610*ef5ccd6cSJohn Marino   *ptr++ = ':';
611*ef5ccd6cSJohn Marino   ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
612*ef5ccd6cSJohn Marino   *ptr++ = ';';
613*ef5ccd6cSJohn Marino 
614*ef5ccd6cSJohn Marino   *ptr++ = hexchars[SP >> 4];
615*ef5ccd6cSJohn Marino   *ptr++ = hexchars[SP & 0xf];
616*ef5ccd6cSJohn Marino   *ptr++ = ':';
617*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&sp, ptr, 4, 0);
618*ef5ccd6cSJohn Marino   *ptr++ = ';';
619*ef5ccd6cSJohn Marino 
620*ef5ccd6cSJohn Marino   *ptr++ = hexchars[NPC >> 4];
621*ef5ccd6cSJohn Marino   *ptr++ = hexchars[NPC & 0xf];
622*ef5ccd6cSJohn Marino   *ptr++ = ':';
623*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
624*ef5ccd6cSJohn Marino   *ptr++ = ';';
625*ef5ccd6cSJohn Marino 
626*ef5ccd6cSJohn Marino   *ptr++ = hexchars[O7 >> 4];
627*ef5ccd6cSJohn Marino   *ptr++ = hexchars[O7 & 0xf];
628*ef5ccd6cSJohn Marino   *ptr++ = ':';
629*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
630*ef5ccd6cSJohn Marino   *ptr++ = ';';
631*ef5ccd6cSJohn Marino 
632*ef5ccd6cSJohn Marino   *ptr++ = 0;
633*ef5ccd6cSJohn Marino 
634*ef5ccd6cSJohn Marino   putpacket(remcomOutBuffer);
635*ef5ccd6cSJohn Marino 
636*ef5ccd6cSJohn Marino   while (1)
637*ef5ccd6cSJohn Marino     {
638*ef5ccd6cSJohn Marino       remcomOutBuffer[0] = 0;
639*ef5ccd6cSJohn Marino 
640*ef5ccd6cSJohn Marino       ptr = getpacket();
641*ef5ccd6cSJohn Marino       switch (*ptr++)
642*ef5ccd6cSJohn Marino 	{
643*ef5ccd6cSJohn Marino 	case '?':
644*ef5ccd6cSJohn Marino 	  remcomOutBuffer[0] = 'S';
645*ef5ccd6cSJohn Marino 	  remcomOutBuffer[1] = hexchars[sigval >> 4];
646*ef5ccd6cSJohn Marino 	  remcomOutBuffer[2] = hexchars[sigval & 0xf];
647*ef5ccd6cSJohn Marino 	  remcomOutBuffer[3] = 0;
648*ef5ccd6cSJohn Marino 	  break;
649*ef5ccd6cSJohn Marino 
650*ef5ccd6cSJohn Marino 	case 'd':		/* toggle debug flag */
651*ef5ccd6cSJohn Marino 	  break;
652*ef5ccd6cSJohn Marino 
653*ef5ccd6cSJohn Marino 	case 'g':		/* return the value of the CPU registers */
654*ef5ccd6cSJohn Marino 	  {
655*ef5ccd6cSJohn Marino 	    ptr = remcomOutBuffer;
656*ef5ccd6cSJohn Marino 	    ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
657*ef5ccd6cSJohn Marino 	    ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
658*ef5ccd6cSJohn Marino 	    memset(ptr, '0', 32 * 8); /* Floating point */
659*ef5ccd6cSJohn Marino 	    mem2hex((char *)&registers[Y],
660*ef5ccd6cSJohn Marino 		    ptr + 32 * 4 * 2,
661*ef5ccd6cSJohn Marino 		    8 * 4,
662*ef5ccd6cSJohn Marino 		    0);		/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
663*ef5ccd6cSJohn Marino 	  }
664*ef5ccd6cSJohn Marino 	  break;
665*ef5ccd6cSJohn Marino 
666*ef5ccd6cSJohn Marino 	case 'G':	   /* set the value of the CPU registers - return OK */
667*ef5ccd6cSJohn Marino 	  {
668*ef5ccd6cSJohn Marino 	    unsigned long *newsp, psr;
669*ef5ccd6cSJohn Marino 
670*ef5ccd6cSJohn Marino 	    psr = registers[PSR];
671*ef5ccd6cSJohn Marino 
672*ef5ccd6cSJohn Marino 	    hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
673*ef5ccd6cSJohn Marino 	    hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
674*ef5ccd6cSJohn Marino 	    hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
675*ef5ccd6cSJohn Marino 		    8 * 4, 0);	/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
676*ef5ccd6cSJohn Marino 
677*ef5ccd6cSJohn Marino 	    /* See if the stack pointer has moved.  If so, then copy the saved
678*ef5ccd6cSJohn Marino 	       locals and ins to the new location.  This keeps the window
679*ef5ccd6cSJohn Marino 	       overflow and underflow routines happy.  */
680*ef5ccd6cSJohn Marino 
681*ef5ccd6cSJohn Marino 	    newsp = (unsigned long *)registers[SP];
682*ef5ccd6cSJohn Marino 	    if (sp != newsp)
683*ef5ccd6cSJohn Marino 	      sp = memcpy(newsp, sp, 16 * 4);
684*ef5ccd6cSJohn Marino 
685*ef5ccd6cSJohn Marino 	    /* Don't allow CWP to be modified. */
686*ef5ccd6cSJohn Marino 
687*ef5ccd6cSJohn Marino 	    if (psr != registers[PSR])
688*ef5ccd6cSJohn Marino 	      registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
689*ef5ccd6cSJohn Marino 
690*ef5ccd6cSJohn Marino 	    strcpy(remcomOutBuffer,"OK");
691*ef5ccd6cSJohn Marino 	  }
692*ef5ccd6cSJohn Marino 	  break;
693*ef5ccd6cSJohn Marino 
694*ef5ccd6cSJohn Marino 	case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
695*ef5ccd6cSJohn Marino 	  /* Try to read %x,%x.  */
696*ef5ccd6cSJohn Marino 
697*ef5ccd6cSJohn Marino 	  if (hexToInt(&ptr, &addr)
698*ef5ccd6cSJohn Marino 	      && *ptr++ == ','
699*ef5ccd6cSJohn Marino 	      && hexToInt(&ptr, &length))
700*ef5ccd6cSJohn Marino 	    {
701*ef5ccd6cSJohn Marino 	      if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
702*ef5ccd6cSJohn Marino 		break;
703*ef5ccd6cSJohn Marino 
704*ef5ccd6cSJohn Marino 	      strcpy (remcomOutBuffer, "E03");
705*ef5ccd6cSJohn Marino 	    }
706*ef5ccd6cSJohn Marino 	  else
707*ef5ccd6cSJohn Marino 	    strcpy(remcomOutBuffer,"E01");
708*ef5ccd6cSJohn Marino 	  break;
709*ef5ccd6cSJohn Marino 
710*ef5ccd6cSJohn Marino 	case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
711*ef5ccd6cSJohn Marino 	  /* Try to read '%x,%x:'.  */
712*ef5ccd6cSJohn Marino 
713*ef5ccd6cSJohn Marino 	  if (hexToInt(&ptr, &addr)
714*ef5ccd6cSJohn Marino 	      && *ptr++ == ','
715*ef5ccd6cSJohn Marino 	      && hexToInt(&ptr, &length)
716*ef5ccd6cSJohn Marino 	      && *ptr++ == ':')
717*ef5ccd6cSJohn Marino 	    {
718*ef5ccd6cSJohn Marino 	      if (hex2mem(ptr, (char *)addr, length, 1))
719*ef5ccd6cSJohn Marino 		strcpy(remcomOutBuffer, "OK");
720*ef5ccd6cSJohn Marino 	      else
721*ef5ccd6cSJohn Marino 		strcpy(remcomOutBuffer, "E03");
722*ef5ccd6cSJohn Marino 	    }
723*ef5ccd6cSJohn Marino 	  else
724*ef5ccd6cSJohn Marino 	    strcpy(remcomOutBuffer, "E02");
725*ef5ccd6cSJohn Marino 	  break;
726*ef5ccd6cSJohn Marino 
727*ef5ccd6cSJohn Marino 	case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
728*ef5ccd6cSJohn Marino 	  /* try to read optional parameter, pc unchanged if no parm */
729*ef5ccd6cSJohn Marino 
730*ef5ccd6cSJohn Marino 	  if (hexToInt(&ptr, &addr))
731*ef5ccd6cSJohn Marino 	    {
732*ef5ccd6cSJohn Marino 	      registers[PC] = addr;
733*ef5ccd6cSJohn Marino 	      registers[NPC] = addr + 4;
734*ef5ccd6cSJohn Marino 	    }
735*ef5ccd6cSJohn Marino 
736*ef5ccd6cSJohn Marino /* Need to flush the instruction cache here, as we may have deposited a
737*ef5ccd6cSJohn Marino    breakpoint, and the icache probably has no way of knowing that a data ref to
738*ef5ccd6cSJohn Marino    some location may have changed something that is in the instruction cache.
739*ef5ccd6cSJohn Marino  */
740*ef5ccd6cSJohn Marino 
741*ef5ccd6cSJohn Marino 	  flush_i_cache();
742*ef5ccd6cSJohn Marino 	  return;
743*ef5ccd6cSJohn Marino 
744*ef5ccd6cSJohn Marino 	  /* kill the program */
745*ef5ccd6cSJohn Marino 	case 'k' :		/* do nothing */
746*ef5ccd6cSJohn Marino 	  break;
747*ef5ccd6cSJohn Marino #if 0
748*ef5ccd6cSJohn Marino 	case 't':		/* Test feature */
749*ef5ccd6cSJohn Marino 	  asm (" std %f30,[%sp]");
750*ef5ccd6cSJohn Marino 	  break;
751*ef5ccd6cSJohn Marino #endif
752*ef5ccd6cSJohn Marino 	case 'r':		/* Reset */
753*ef5ccd6cSJohn Marino 	  asm ("call 0
754*ef5ccd6cSJohn Marino 		nop ");
755*ef5ccd6cSJohn Marino 	  break;
756*ef5ccd6cSJohn Marino 	}			/* switch */
757*ef5ccd6cSJohn Marino 
758*ef5ccd6cSJohn Marino       /* reply to the request */
759*ef5ccd6cSJohn Marino       putpacket(remcomOutBuffer);
760*ef5ccd6cSJohn Marino     }
761*ef5ccd6cSJohn Marino }
762*ef5ccd6cSJohn Marino 
763*ef5ccd6cSJohn Marino /* This function will generate a breakpoint exception.  It is used at the
764*ef5ccd6cSJohn Marino    beginning of a program to sync up with a debugger and can be used
765*ef5ccd6cSJohn Marino    otherwise as a quick means to stop program execution and "break" into
766*ef5ccd6cSJohn Marino    the debugger. */
767*ef5ccd6cSJohn Marino 
768*ef5ccd6cSJohn Marino void
breakpoint(void)769*ef5ccd6cSJohn Marino breakpoint (void)
770*ef5ccd6cSJohn Marino {
771*ef5ccd6cSJohn Marino   if (!initialized)
772*ef5ccd6cSJohn Marino     return;
773*ef5ccd6cSJohn Marino 
774*ef5ccd6cSJohn Marino   asm("	.globl _breakinst
775*ef5ccd6cSJohn Marino 
776*ef5ccd6cSJohn Marino 	_breakinst: ta 1
777*ef5ccd6cSJohn Marino       ");
778*ef5ccd6cSJohn Marino }
779