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