newlib: Regenerate autotools files
[newlib-cygwin.git] / libgloss / sparc / sparcl-stub.c
blob960e1a6660332afc14807c6f2807b2cc829fe191
1 /****************************************************************************
3 THIS SOFTWARE IS NOT COPYRIGHTED
5 HP offers the following for use in the public domain. HP makes no
6 warranty with regard to the software or its performance and the
7 user accepts the software "AS IS" with all faults.
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.
13 ****************************************************************************/
15 /****************************************************************************
16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
18 * Module name: remcom.c $
19 * Revision: 1.34 $
20 * Date: 91/03/09 12:29:49 $
21 * Contributor: Lake Stevens Instrument Division$
23 * Description: low level support for gdb debugger. $
25 * Considerations: only works on target hardware $
27 * Written by: Glenn Engel $
28 * ModuleState: Experimental $
30 * NOTES: See Below $
32 * Modified for SPARC by Stu Grossman, Cygnus Support.
33 * Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware
34 * breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support.
36 * This code has been extensively tested on the Fujitsu SPARClite demo board.
38 * To enable debugger support, two things need to happen. One, a
39 * call to set_debug_traps() is necessary in order to allow any breakpoints
40 * or error conditions to be properly intercepted and reported to gdb.
41 * Two, a breakpoint needs to be generated to begin communication. This
42 * is most easily accomplished by a call to breakpoint(). Breakpoint()
43 * simulates a breakpoint by executing a trap #1.
45 *************
47 * The following gdb commands are supported:
49 * command function Return value
51 * g return the value of the CPU registers hex data or ENN
52 * G set the value of the CPU registers OK or ENN
54 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
55 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
57 * c Resume at current address SNN ( signal NN)
58 * cAA..AA Continue at address AA..AA SNN
60 * s Step one instruction SNN
61 * sAA..AA Step one instruction from AA..AA SNN
63 * k kill
65 * ? What was the last sigval ? SNN (signal NN)
67 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
68 * baud rate
70 * All commands and responses are sent with a packet which includes a
71 * checksum. A packet consists of
73 * $<packet info>#<checksum>.
75 * where
76 * <packet info> :: <characters representing the command or response>
77 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
79 * When a packet is received, it is first acknowledged with either '+' or '-'.
80 * '+' indicates a successful transfer. '-' indicates a failed transfer.
82 * Example:
84 * Host: Reply:
85 * $m0,10#2a +$00010203040506070809101112131415#42
87 ****************************************************************************/
89 #include <string.h>
90 #include <signal.h>
91 #include "asm.h"
93 /************************************************************************
95 * external low-level support routines
97 extern putDebugChar(); /* write a single character */
98 extern getDebugChar(); /* read and return a single char */
100 /* Pointer to hook for outbyte, set by stub's exception handler. */
101 extern void (*__outbyte_hook)();
103 /************************************************************************/
104 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
105 /* at least NUMREGBYTES*2 are needed for register packets */
106 #define BUFMAX 2048
108 static int initialized = 0; /* !0 means we've been initialized */
110 extern void breakinst();
111 static void hw_breakpoint();
112 static void set_mem_fault_trap();
113 static void get_in_break_mode();
115 static const char hexchars[]="0123456789abcdef";
117 #define NUMREGS 80
119 /* Number of bytes of registers. */
120 #define NUMREGBYTES (NUMREGS * 4)
121 enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
122 O0, O1, O2, O3, O4, O5, SP, O7,
123 L0, L1, L2, L3, L4, L5, L6, L7,
124 I0, I1, I2, I3, I4, I5, FP, I7,
126 F0, F1, F2, F3, F4, F5, F6, F7,
127 F8, F9, F10, F11, F12, F13, F14, F15,
128 F16, F17, F18, F19, F20, F21, F22, F23,
129 F24, F25, F26, F27, F28, F29, F30, F31,
130 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR,
131 DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR };
133 /*************************** ASSEMBLY CODE MACROS *************************/
134 /* */
136 extern void trap_low();
138 asm("
139 .reserve trapstack, 1000 * 4, \"bss\", 8
141 .data
142 .align 4
144 in_trap_handler:
145 .word 0
147 .text
148 .align 4
150 ! This function is called when any SPARC trap (except window overflow or
151 ! underflow) occurs. It makes sure that the invalid register window is still
152 ! available before jumping into C code. It will also restore the world if you
153 ! return from handle_exception.
155 .globl " STRINGSYM(trap_low) "
156 " STRINGSYM(trap_low) ":
157 mov %psr, %l0
158 mov %wim, %l3
160 srl %l3, %l0, %l4 ! wim >> cwp
161 cmp %l4, 1
162 bne window_fine ! Branch if not in the invalid window
165 ! Handle window overflow
167 mov %g1, %l4 ! Save g1, we use it to hold the wim
168 srl %l3, 1, %g1 ! Rotate wim right
169 tst %g1
170 bg good_wim ! Branch if new wim is non-zero
173 ! At this point, we need to bring a 1 into the high order bit of the wim.
174 ! Since we don't want to make any assumptions about the number of register
175 ! windows, we figure it out dynamically so as to setup the wim correctly.
177 not %g1 ! Fill g1 with ones
178 mov %g1, %wim ! Fill the wim with ones
182 mov %wim, %g1 ! Read back the wim
183 inc %g1 ! Now g1 has 1 just to left of wim
184 srl %g1, 1, %g1 ! Now put 1 at top of wim
185 mov %g0, %wim ! Clear wim so that subsequent save
186 nop ! won't trap
190 good_wim:
191 save %g0, %g0, %g0 ! Slip into next window
192 mov %g1, %wim ! Install the new wim
194 std %l0, [%sp + 0 * 4] ! save L & I registers
195 std %l2, [%sp + 2 * 4]
196 std %l4, [%sp + 4 * 4]
197 std %l6, [%sp + 6 * 4]
199 std %i0, [%sp + 8 * 4]
200 std %i2, [%sp + 10 * 4]
201 std %i4, [%sp + 12 * 4]
202 std %i6, [%sp + 14 * 4]
204 restore ! Go back to trap window.
205 mov %l4, %g1 ! Restore %g1
207 window_fine:
208 sethi %hi(in_trap_handler), %l4
209 ld [%lo(in_trap_handler) + %l4], %l5
210 tst %l5
211 bg recursive_trap
212 inc %l5
214 set trapstack+1000*4, %sp ! Switch to trap stack
216 recursive_trap:
217 st %l5, [%lo(in_trap_handler) + %l4]
218 sub %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals
219 ! + hidden arg + arg spill
220 ! + doubleword alignment
221 ! + registers[72] local var
223 std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
224 std %g2, [%sp + (24 + 2) * 4]
225 std %g4, [%sp + (24 + 4) * 4]
226 std %g6, [%sp + (24 + 6) * 4]
228 std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
229 std %i2, [%sp + (24 + 10) * 4]
230 std %i4, [%sp + (24 + 12) * 4]
231 std %i6, [%sp + (24 + 14) * 4]
232 ! F0->F31 not implemented
233 mov %y, %l4
234 mov %tbr, %l5
235 st %l4, [%sp + (24 + 64) * 4] ! Y
236 st %l0, [%sp + (24 + 65) * 4] ! PSR
237 st %l3, [%sp + (24 + 66) * 4] ! WIM
238 st %l5, [%sp + (24 + 67) * 4] ! TBR
239 st %l1, [%sp + (24 + 68) * 4] ! PC
240 st %l2, [%sp + (24 + 69) * 4] ! NPC
241 ! CPSR and FPSR not impl
242 or %l0, 0xf20, %l4
243 mov %l4, %psr ! Turn on traps, disable interrupts
247 call " STRINGSYM(get_in_break_mode) "
252 sethi %hi(0xff00), %l5
253 or %l5, %lo(0xff00), %l5
255 lda [%l5]0x1, %l4
256 st %l4, [%sp + (24 + 72) * 4] ! DIA1, debug instr addr 1
257 add %l5, 4, %l5
258 lda [%l5]0x1, %l4
259 st %l4, [%sp + (24 + 73) * 4] ! DIA2, debug instr addr 2
260 add %l5, 4, %l5
261 lda [%l5]0x1, %l4
262 st %l4, [%sp + (24 + 74) * 4] ! DDA1, debug data addr 1
263 add %l5, 4, %l5
264 lda [%l5]0x1, %l4
265 st %l4, [%sp + (24 + 75) * 4] ! DDA2, debug data addr 2
266 add %l5, 4, %l5
267 lda [%l5]0x1, %l4
268 st %l4, [%sp + (24 + 76) * 4] ! DDV1, debug data val 1
269 add %l5, 4, %l5
270 lda [%l5]0x1, %l4
271 st %l4, [%sp + (24 + 77) * 4] ! DDV2, debug data val 2
272 add %l5, 4, %l5
273 lda [%l5]0x1, %l4
274 st %l4, [%sp + (24 + 78) * 4] ! DCR, debug control reg
275 add %l5, 4, %l5
276 lda [%l5]0x1, %l4
277 st %l4, [%sp + (24 + 79) * 4] ! DSR, debug status reg
280 or %l0, 0xf20, %l4
281 mov %l4, %psr ! Turn on traps, disable interrupts
285 call " STRINGSYM(handle_exception) "
286 add %sp, 24 * 4, %o0 ! Pass address of registers
288 ! Reload all of the registers that aren't on the stack
290 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
291 ldd [%sp + (24 + 2) * 4], %g2
292 ldd [%sp + (24 + 4) * 4], %g4
293 ldd [%sp + (24 + 6) * 4], %g6
295 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
296 ldd [%sp + (24 + 10) * 4], %i2
297 ldd [%sp + (24 + 12) * 4], %i4
298 ldd [%sp + (24 + 14) * 4], %i6
300 sethi %hi(0xff00), %l2
301 or %l2, %lo(0xff00), %l2
302 ldd [%sp + (24 + 72) * 4], %l4 ! DIA1, debug instr addr 1
303 stda %l4, [%l2]0x1
308 ldd [%sp + (24 + 74) * 4], %l4 ! DDA1, debug data addr 1
309 add %l2, 8, %l2
310 stda %l4, [%l2]0x1
315 ldd [%sp + (24 + 76) * 4], %l4 ! DDV1, debug data value 1
316 add %l2, 8, %l2
317 stda %l4, [%l2]0x1
322 ld [%sp + (24 + 78) * 4], %l4 ! DCR, debug control reg
323 ld [%sp + (24 + 79) * 4], %l5 ! DSR, debug control reg
324 add %l2, 8, %l2
325 or %l4, 0x200, %l4
326 sta %l4, [%l2]0x1
327 add %l2, 4, %l2
328 sta %l5, [%l2]0x1
334 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
335 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
337 restore ! Ensure that previous window is valid
338 save %g0, %g0, %g0 ! by causing a window_underflow trap
340 mov %l0, %y
341 mov %l1, %psr ! Make sure that traps are disabled
342 ! for rett
343 sethi %hi(in_trap_handler), %l4
344 ld [%lo(in_trap_handler) + %l4], %l5
345 dec %l5
346 st %l5, [%lo(in_trap_handler) + %l4]
348 jmpl %l2, %g0 ! Restore old PC
349 rett %l3 ! Restore old nPC
352 /* Convert ch from a hex digit to an int */
354 static int
355 hex(ch)
356 unsigned char ch;
358 if (ch >= 'a' && ch <= 'f')
359 return ch-'a'+10;
360 if (ch >= '0' && ch <= '9')
361 return ch-'0';
362 if (ch >= 'A' && ch <= 'F')
363 return ch-'A'+10;
364 return -1;
367 /* scan for the sequence $<data>#<checksum> */
369 static void
370 getpacket(buffer)
371 char *buffer;
373 unsigned char checksum;
374 unsigned char xmitcsum;
375 int i;
376 int count;
377 unsigned char ch;
381 /* wait around for the start character, ignore all other characters */
382 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
384 checksum = 0;
385 xmitcsum = -1;
387 count = 0;
389 /* now, read until a # or end of buffer is found */
390 while (count < BUFMAX)
392 ch = getDebugChar() & 0x7f;
393 if (ch == '#')
394 break;
395 checksum = checksum + ch;
396 buffer[count] = ch;
397 count = count + 1;
400 if (count >= BUFMAX)
401 continue;
403 buffer[count] = 0;
405 if (ch == '#')
407 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
408 xmitcsum |= hex(getDebugChar() & 0x7f);
409 #if 0
410 /* Humans shouldn't have to figure out checksums to type to it. */
411 putDebugChar ('+');
412 return;
413 #endif
414 if (checksum != xmitcsum)
415 putDebugChar('-'); /* failed checksum */
416 else
418 putDebugChar('+'); /* successful transfer */
419 /* if a sequence char is present, reply the sequence ID */
420 if (buffer[2] == ':')
422 putDebugChar(buffer[0]);
423 putDebugChar(buffer[1]);
424 /* remove sequence chars from buffer */
425 count = strlen(buffer);
426 for (i=3; i <= count; i++)
427 buffer[i-3] = buffer[i];
432 while (checksum != xmitcsum);
435 /* send the packet in buffer. */
437 static void
438 putpacket(buffer)
439 unsigned char *buffer;
441 unsigned char checksum;
442 int count;
443 unsigned char ch;
445 /* $<packet info>#<checksum>. */
448 putDebugChar('$');
449 checksum = 0;
450 count = 0;
452 while (ch = buffer[count])
454 if (! putDebugChar(ch))
455 return;
456 checksum += ch;
457 count += 1;
460 putDebugChar('#');
461 putDebugChar(hexchars[checksum >> 4]);
462 putDebugChar(hexchars[checksum & 0xf]);
465 while ((getDebugChar() & 0x7f) != '+');
468 static char remcomInBuffer[BUFMAX];
469 static char remcomOutBuffer[BUFMAX];
471 /* Indicate to caller of mem2hex or hex2mem that there has been an
472 error. */
473 static volatile int mem_err = 0;
475 /* Convert the memory pointed to by mem into hex, placing result in buf.
476 * Return a pointer to the last char put in buf (null), in case of mem fault,
477 * return 0.
478 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
479 * a 0, else treat a fault like any other fault in the stub.
482 static unsigned char *
483 mem2hex(mem, buf, count, may_fault)
484 unsigned char *mem;
485 unsigned char *buf;
486 int count;
487 int may_fault;
489 unsigned char ch;
491 set_mem_fault_trap(may_fault);
493 while (count-- > 0)
495 ch = *mem++;
496 if (mem_err)
497 return 0;
498 *buf++ = hexchars[ch >> 4];
499 *buf++ = hexchars[ch & 0xf];
502 *buf = 0;
504 set_mem_fault_trap(0);
506 return buf;
509 /* convert the hex array pointed to by buf into binary to be placed in mem
510 * return a pointer to the character AFTER the last byte written */
512 static char *
513 hex2mem(buf, mem, count, may_fault)
514 unsigned char *buf;
515 unsigned char *mem;
516 int count;
517 int may_fault;
519 int i;
520 unsigned char ch;
522 set_mem_fault_trap(may_fault);
524 for (i=0; i<count; i++)
526 ch = hex(*buf++) << 4;
527 ch |= hex(*buf++);
528 *mem++ = ch;
529 if (mem_err)
530 return 0;
533 set_mem_fault_trap(0);
535 return mem;
538 /* This table contains the mapping between SPARC hardware trap types, and
539 signals, which are primarily what GDB understands. It also indicates
540 which hardware traps we need to commandeer when initializing the stub. */
542 static struct hard_trap_info
544 unsigned char tt; /* Trap type code for SPARClite */
545 unsigned char signo; /* Signal that we map this trap into */
546 } hard_trap_info[] = {
547 {1, SIGSEGV}, /* instruction access error */
548 {2, SIGILL}, /* privileged instruction */
549 {3, SIGILL}, /* illegal instruction */
550 {4, SIGEMT}, /* fp disabled */
551 {36, SIGEMT}, /* cp disabled */
552 {7, SIGBUS}, /* mem address not aligned */
553 {9, SIGSEGV}, /* data access exception */
554 {10, SIGEMT}, /* tag overflow */
555 {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
556 {255, SIGTRAP}, /* hardware breakpoint */
557 {0, 0} /* Must be last */
560 /* Set up exception handlers for tracing and breakpoints */
562 void
563 set_debug_traps()
565 struct hard_trap_info *ht;
567 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
568 exceptionHandler(ht->tt, trap_low);
570 /* In case GDB is started before us, ack any packets (presumably
571 "$?#xx") sitting there. */
573 putDebugChar ('+');
575 initialized = 1;
578 asm ("
579 ! Trap handler for memory errors. This just sets mem_err to be non-zero. It
580 ! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
581 ! 0 would ever contain code that could mem fault. This routine will skip
582 ! past the faulting instruction after setting mem_err.
584 .text
585 .align 4
587 " STRINGSYM(fltr_set_mem_err) ":
588 sethi %hi(" STRINGSYM(mem_err) "), %l0
589 st %l1, [%l0 + %lo(" STRINGSYM(mem_err) ")]
590 jmpl %l2, %g0
591 rett %l2+4
594 static void
595 set_mem_fault_trap(enable)
596 int enable;
598 extern void fltr_set_mem_err();
599 mem_err = 0;
601 if (enable)
602 exceptionHandler(9, fltr_set_mem_err);
603 else
604 exceptionHandler(9, trap_low);
607 asm ("
608 .text
609 .align 4
611 " STRINGSYM(dummy_hw_breakpoint) ":
612 jmpl %l2, %g0
613 rett %l2+4
618 static void
619 set_hw_breakpoint_trap(enable)
620 int enable;
622 extern void dummy_hw_breakpoint();
624 if (enable)
625 exceptionHandler(255, dummy_hw_breakpoint);
626 else
627 exceptionHandler(255, trap_low);
630 static void
631 get_in_break_mode()
633 set_hw_breakpoint_trap(1);
635 asm("
636 sethi %hi(0xff10), %l4
637 or %l4, %lo(0xff10), %l4
638 sta %g0, [%l4]0x1
644 set_hw_breakpoint_trap(0);
647 /* Convert the SPARC hardware trap type code to a unix signal number. */
649 static int
650 computeSignal(tt)
651 int tt;
653 struct hard_trap_info *ht;
655 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
656 if (ht->tt == tt)
657 return ht->signo;
659 return SIGHUP; /* default for things we don't know about */
663 * While we find nice hex chars, build an int.
664 * Return number of chars processed.
667 static int
668 hexToInt(char **ptr, int *intValue)
670 int numChars = 0;
671 int hexValue;
673 *intValue = 0;
675 while (**ptr)
677 hexValue = hex(**ptr);
678 if (hexValue < 0)
679 break;
681 *intValue = (*intValue << 4) | hexValue;
682 numChars ++;
684 (*ptr)++;
687 return (numChars);
690 /* Replacement for outbyte that sends a packet to GDB containing
691 the character to be output. */
693 static void
694 outbyte_stub (int c)
696 static char buf[4];
698 buf[0] = 'O';
699 buf[1] = hexchars[(c >> 4) & 0xf];
700 buf[2] = hexchars[c % 16];
701 buf[3] = 0;
702 putpacket (buf);
707 * This function does all command procesing for interfacing to gdb. It
708 * returns 1 if you should skip the instruction at the trap address, 0
709 * otherwise.
713 static void
714 handle_exception (registers)
715 unsigned long *registers;
717 int tt; /* Trap type */
718 int sigval;
719 int addr;
720 int length;
721 char *ptr;
722 unsigned long *sp;
723 unsigned long dsr;
725 /* First, we must force all of the windows to be spilled out */
727 asm(" save %sp, -64, %sp
728 save %sp, -64, %sp
729 save %sp, -64, %sp
730 save %sp, -64, %sp
731 save %sp, -64, %sp
732 save %sp, -64, %sp
733 save %sp, -64, %sp
734 save %sp, -64, %sp
735 restore
736 restore
737 restore
738 restore
739 restore
740 restore
741 restore
742 restore
745 if (registers[PC] == (unsigned long)breakinst)
747 registers[PC] = registers[NPC];
748 registers[NPC] += 4;
750 sp = (unsigned long *)registers[SP];
752 dsr = (unsigned long)registers[DSR];
753 if (dsr & 0x3c)
755 tt = 255;
757 else
759 tt = (registers[TBR] >> 4) & 0xff;
762 /* reply to host that an exception has occurred */
763 sigval = computeSignal(tt);
764 ptr = remcomOutBuffer;
766 *ptr++ = 'T';
767 *ptr++ = hexchars[sigval >> 4];
768 *ptr++ = hexchars[sigval & 0xf];
770 *ptr++ = hexchars[PC >> 4];
771 *ptr++ = hexchars[PC & 0xf];
772 *ptr++ = ':';
773 ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
774 *ptr++ = ';';
776 *ptr++ = hexchars[FP >> 4];
777 *ptr++ = hexchars[FP & 0xf];
778 *ptr++ = ':';
779 ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
780 *ptr++ = ';';
782 *ptr++ = hexchars[SP >> 4];
783 *ptr++ = hexchars[SP & 0xf];
784 *ptr++ = ':';
785 ptr = mem2hex((char *)&sp, ptr, 4, 0);
786 *ptr++ = ';';
788 *ptr++ = hexchars[NPC >> 4];
789 *ptr++ = hexchars[NPC & 0xf];
790 *ptr++ = ':';
791 ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
792 *ptr++ = ';';
794 *ptr++ = hexchars[O7 >> 4];
795 *ptr++ = hexchars[O7 & 0xf];
796 *ptr++ = ':';
797 ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
798 *ptr++ = ';';
800 *ptr++ = 0;
802 putpacket(remcomOutBuffer);
804 __outbyte_hook = outbyte_stub;
806 while (1)
808 remcomOutBuffer[0] = 0;
810 getpacket(remcomInBuffer);
811 switch (remcomInBuffer[0])
813 case '?':
814 remcomOutBuffer[0] = 'S';
815 remcomOutBuffer[1] = hexchars[sigval >> 4];
816 remcomOutBuffer[2] = hexchars[sigval & 0xf];
817 remcomOutBuffer[3] = 0;
818 break;
820 case 'd':
821 /* toggle debug flag */
822 break;
824 case 'g': /* return the value of the CPU registers */
826 ptr = remcomOutBuffer;
827 ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
828 ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
829 memset(ptr, '0', 32 * 8); /* Floating point */
830 ptr = mem2hex((char *)&registers[Y],
831 ptr + 32 * 4 * 2,
832 8 * 4,
833 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
834 mem2hex((char *)&registers[DIA1], ptr,
835 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */
837 break;
839 case 'G': /* set the value of the CPU registers - return OK */
841 unsigned long *newsp, psr;
843 psr = registers[PSR];
845 ptr = &remcomInBuffer[1];
846 hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
847 hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
848 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
849 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
850 hex2mem(ptr + 72 * 4 * 2, (char *)&registers[DIA1],
851 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */
853 /* See if the stack pointer has moved. If so, then copy the saved
854 locals and ins to the new location. This keeps the window
855 overflow and underflow routines happy. */
857 newsp = (unsigned long *)registers[SP];
858 if (sp != newsp)
859 sp = memcpy(newsp, sp, 16 * 4);
861 /* Don't allow CWP to be modified. */
863 if (psr != registers[PSR])
864 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
866 strcpy(remcomOutBuffer,"OK");
868 break;
870 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
871 /* Try to read %x,%x. */
873 ptr = &remcomInBuffer[1];
875 if (hexToInt(&ptr, &addr)
876 && *ptr++ == ','
877 && hexToInt(&ptr, &length))
879 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
880 break;
882 strcpy (remcomOutBuffer, "E03");
884 else
885 strcpy(remcomOutBuffer,"E01");
886 break;
888 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
889 /* Try to read '%x,%x:'. */
891 ptr = &remcomInBuffer[1];
893 if (hexToInt(&ptr, &addr)
894 && *ptr++ == ','
895 && hexToInt(&ptr, &length)
896 && *ptr++ == ':')
898 if (hex2mem(ptr, (char *)addr, length, 1))
899 strcpy(remcomOutBuffer, "OK");
900 else
901 strcpy(remcomOutBuffer, "E03");
903 else
904 strcpy(remcomOutBuffer, "E02");
905 break;
907 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
908 /* try to read optional parameter, pc unchanged if no parm */
910 ptr = &remcomInBuffer[1];
911 if (hexToInt(&ptr, &addr))
913 registers[PC] = addr;
914 registers[NPC] = addr + 4;
917 /* Need to flush the instruction cache here, as we may have deposited a
918 breakpoint, and the icache probably has no way of knowing that a data ref to
919 some location may have changed something that is in the instruction cache.
922 flush_i_cache();
923 return;
925 /* kill the program */
926 case 'k' : /* do nothing */
927 break;
928 #if 0
929 case 't': /* Test feature */
930 asm (" std %f30,[%sp]");
931 break;
932 #endif
933 case 'r': /* Reset */
934 asm ("call 0
935 nop ");
936 break;
938 #if 0
939 Disabled until we can unscrew this properly
941 case 'b': /* bBB... Set baud rate to BB... */
943 int baudrate;
944 extern void set_timer_3();
946 ptr = &remcomInBuffer[1];
947 if (!hexToInt(&ptr, &baudrate))
949 strcpy(remcomOutBuffer,"B01");
950 break;
953 /* Convert baud rate to uart clock divider */
954 switch (baudrate)
956 case 38400:
957 baudrate = 16;
958 break;
959 case 19200:
960 baudrate = 33;
961 break;
962 case 9600:
963 baudrate = 65;
964 break;
965 default:
966 strcpy(remcomOutBuffer,"B02");
967 goto x1;
970 putpacket("OK"); /* Ack before changing speed */
971 set_timer_3(baudrate); /* Set it */
973 x1: break;
974 #endif
975 } /* switch */
977 /* reply to the request */
978 putpacket(remcomOutBuffer);
982 /* This function will generate a breakpoint exception. It is used at the
983 beginning of a program to sync up with a debugger and can be used
984 otherwise as a quick means to stop program execution and "break" into
985 the debugger. */
987 void
988 breakpoint()
990 if (!initialized)
991 return;
993 asm(" .globl " STRINGSYM(breakinst) "
995 " STRINGSYM(breakinst) ": ta 1
999 static void
1000 hw_breakpoint()
1002 asm("
1003 ta 127