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 *)®isters[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 *)®isters[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 *)®isters[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 *)®isters[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 *)®isters[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