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