source: trunk/libs/newlib/src/libgloss/sparc/sparcl-stub.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 23.3 KB
Line 
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#include "asm.h"
92
93/************************************************************************
94 *
95 * external low-level support routines
96 */
97extern putDebugChar();   /* write a single character      */
98extern getDebugChar();   /* read and return a single char */
99
100/* Pointer to hook for outbyte, set by stub's exception handler.  */
101extern void (*__outbyte_hook)();
102
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
107
108static int initialized = 0;     /* !0 means we've been initialized */
109
110extern void breakinst();
111static void hw_breakpoint();
112static void set_mem_fault_trap();
113static void get_in_break_mode();
114
115static const char hexchars[]="0123456789abcdef";
116
117#define NUMREGS 80
118
119/* Number of bytes of registers.  */
120#define NUMREGBYTES (NUMREGS * 4)
121enum 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,
125
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 };
132
133/***************************  ASSEMBLY CODE MACROS *************************/
134/*                                                                         */
135
136extern void trap_low();
137
138asm("
139        .reserve trapstack, 1000 * 4, \"bss\", 8
140
141        .data
142        .align  4
143
144in_trap_handler:
145        .word   0
146
147        .text
148        .align 4
149
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.
154
155        .globl " STRINGSYM(trap_low) "
156" STRINGSYM(trap_low) ":
157        mov     %psr, %l0
158        mov     %wim, %l3
159
160        srl     %l3, %l0, %l4           ! wim >> cwp
161        cmp     %l4, 1
162        bne     window_fine             ! Branch if not in the invalid window
163        nop
164
165! Handle window overflow
166
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
171        nop
172
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.
176
177        not     %g1                     ! Fill g1 with ones
178        mov     %g1, %wim               ! Fill the wim with ones
179        nop
180        nop
181        nop
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
187        nop
188        nop
189
190good_wim:
191        save    %g0, %g0, %g0           ! Slip into next window
192        mov     %g1, %wim               ! Install the new wim
193
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]
198
199        std     %i0, [%sp + 8 * 4]
200        std     %i2, [%sp + 10 * 4]
201        std     %i4, [%sp + 12 * 4]
202        std     %i6, [%sp + 14 * 4]
203
204        restore                         ! Go back to trap window.
205        mov     %l4, %g1                ! Restore %g1
206
207window_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
213
214        set     trapstack+1000*4, %sp   ! Switch to trap stack
215
216recursive_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
222
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]
227
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
244        nop
245        nop
246        nop
247        call    " STRINGSYM(get_in_break_mode) "
248        nop
249        nop
250        nop
251
252        sethi   %hi(0xff00), %l5
253        or      %l5, %lo(0xff00), %l5
254
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
278        nop
279        nop
280        or      %l0, 0xf20, %l4
281        mov     %l4, %psr               ! Turn on traps, disable interrupts
282        nop
283        nop
284        nop
285        call    " STRINGSYM(handle_exception) "
286        add     %sp, 24 * 4, %o0        ! Pass address of registers
287
288! Reload all of the registers that aren't on the stack
289
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
294
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
299
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 
304        nop
305        nop
306        nop
307        nop
308        ldd     [%sp + (24 + 74) * 4], %l4 ! DDA1, debug data addr 1
309        add     %l2, 8, %l2
310        stda    %l4, [%l2]0x1 
311        nop
312        nop
313        nop
314        nop
315        ldd     [%sp + (24 + 76) * 4], %l4 ! DDV1, debug data value 1
316        add     %l2, 8, %l2
317        stda    %l4, [%l2]0x1 
318        nop
319        nop
320        nop
321        nop
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
329        nop
330        nop
331        nop
332        nop
333
334        ldd     [%sp + (24 + 64) * 4], %l0 ! Y & PSR
335        ldd     [%sp + (24 + 68) * 4], %l2 ! PC & NPC
336
337        restore                         ! Ensure that previous window is valid
338        save    %g0, %g0, %g0           !  by causing a window_underflow trap
339
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]
347
348        jmpl    %l2, %g0                ! Restore old PC
349        rett    %l3                     ! Restore old nPC
350");
351
352/* Convert ch from a hex digit to an int */
353
354static int
355hex(ch)
356     unsigned char ch;
357{
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;
365}
366
367/* scan for the sequence $<data>#<checksum>     */
368
369static void
370getpacket(buffer)
371     char *buffer;
372{
373  unsigned char checksum;
374  unsigned char xmitcsum;
375  int i;
376  int count;
377  unsigned char ch;
378
379  do
380    {
381      /* wait around for the start character, ignore all other characters */
382      while ((ch = (getDebugChar() & 0x7f)) != '$') ;
383
384      checksum = 0;
385      xmitcsum = -1;
386
387      count = 0;
388
389      /* now, read until a # or end of buffer is found */
390      while (count < BUFMAX)
391        {
392          ch = getDebugChar() & 0x7f;
393          if (ch == '#')
394            break;
395          checksum = checksum + ch;
396          buffer[count] = ch;
397          count = count + 1;
398        }
399
400      if (count >= BUFMAX)
401        continue;
402
403      buffer[count] = 0;
404
405      if (ch == '#')
406        {
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
417            {
418              putDebugChar('+'); /* successful transfer */
419              /* if a sequence char is present, reply the sequence ID */
420              if (buffer[2] == ':')
421                {
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];
428                }
429            }
430        }
431    }
432  while (checksum != xmitcsum);
433}
434
435/* send the packet in buffer.  */
436
437static void
438putpacket(buffer)
439     unsigned char *buffer;
440{
441  unsigned char checksum;
442  int count;
443  unsigned char ch;
444
445  /*  $<packet info>#<checksum>. */
446  do
447    {
448      putDebugChar('$');
449      checksum = 0;
450      count = 0;
451
452      while (ch = buffer[count])
453        {
454          if (! putDebugChar(ch))
455            return;
456          checksum += ch;
457          count += 1;
458        }
459
460      putDebugChar('#');
461      putDebugChar(hexchars[checksum >> 4]);
462      putDebugChar(hexchars[checksum & 0xf]);
463
464    }
465  while ((getDebugChar() & 0x7f) != '+');
466}
467
468static char remcomInBuffer[BUFMAX];
469static char remcomOutBuffer[BUFMAX];
470
471/* Indicate to caller of mem2hex or hex2mem that there has been an
472   error.  */
473static volatile int mem_err = 0;
474
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.
480 */
481
482static unsigned char *
483mem2hex(mem, buf, count, may_fault)
484     unsigned char *mem;
485     unsigned char *buf;
486     int count;
487     int may_fault;
488{
489  unsigned char ch;
490
491  set_mem_fault_trap(may_fault);
492
493  while (count-- > 0)
494    {
495      ch = *mem++;
496      if (mem_err)
497        return 0;
498      *buf++ = hexchars[ch >> 4];
499      *buf++ = hexchars[ch & 0xf];
500    }
501
502  *buf = 0;
503
504  set_mem_fault_trap(0);
505
506  return buf;
507}
508
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 */
511
512static char *
513hex2mem(buf, mem, count, may_fault)
514     unsigned char *buf;
515     unsigned char *mem;
516     int count;
517     int may_fault;
518{
519  int i;
520  unsigned char ch;
521
522  set_mem_fault_trap(may_fault);
523
524  for (i=0; i<count; i++)
525    {
526      ch = hex(*buf++) << 4;
527      ch |= hex(*buf++);
528      *mem++ = ch;
529      if (mem_err)
530        return 0;
531    }
532
533  set_mem_fault_trap(0);
534
535  return mem;
536}
537
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. */
541
542static struct hard_trap_info
543{
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 */
558};
559
560/* Set up exception handlers for tracing and breakpoints */
561
562void
563set_debug_traps()
564{
565  struct hard_trap_info *ht;
566
567  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
568    exceptionHandler(ht->tt, trap_low);
569
570  /* In case GDB is started before us, ack any packets (presumably
571     "$?#xx") sitting there.  */
572
573  putDebugChar ('+');
574
575  initialized = 1;
576}
577
578asm ("
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.
583
584        .text
585        .align 4
586
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
592");
593
594static void
595set_mem_fault_trap(enable)
596     int enable;
597{
598  extern void fltr_set_mem_err();
599  mem_err = 0;
600
601  if (enable)
602    exceptionHandler(9, fltr_set_mem_err);
603  else
604    exceptionHandler(9, trap_low);
605}
606
607asm ("
608        .text
609        .align 4
610
611" STRINGSYM(dummy_hw_breakpoint) ":
612        jmpl %l2, %g0
613        rett %l2+4
614        nop
615        nop
616");
617
618static void
619set_hw_breakpoint_trap(enable)
620     int enable;
621{
622  extern void dummy_hw_breakpoint();
623
624  if (enable)
625    exceptionHandler(255, dummy_hw_breakpoint);
626  else
627    exceptionHandler(255, trap_low);
628}
629
630static void
631get_in_break_mode()
632{
633  set_hw_breakpoint_trap(1);
634
635  asm("
636        sethi   %hi(0xff10), %l4
637        or      %l4, %lo(0xff10), %l4
638        sta     %g0, [%l4]0x1   
639        nop
640        nop
641        nop
642      ");
643
644  set_hw_breakpoint_trap(0);
645}
646
647/* Convert the SPARC hardware trap type code to a unix signal number. */
648
649static int
650computeSignal(tt)
651     int tt;
652{
653  struct hard_trap_info *ht;
654
655  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
656    if (ht->tt == tt)
657      return ht->signo;
658
659  return SIGHUP;                /* default for things we don't know about */
660}
661
662/*
663 * While we find nice hex chars, build an int.
664 * Return number of chars processed.
665 */
666
667static int
668hexToInt(char **ptr, int *intValue)
669{
670  int numChars = 0;
671  int hexValue;
672
673  *intValue = 0;
674
675  while (**ptr)
676    {
677      hexValue = hex(**ptr);
678      if (hexValue < 0)
679        break;
680
681      *intValue = (*intValue << 4) | hexValue;
682      numChars ++;
683
684      (*ptr)++;
685    }
686
687  return (numChars);
688}
689
690/* Replacement for outbyte that sends a packet to GDB containing
691   the character to be output.  */
692
693static void
694outbyte_stub (int c)
695{
696  static char buf[4];
697
698  buf[0] = 'O';
699  buf[1] = hexchars[(c >> 4) & 0xf];
700  buf[2] = hexchars[c % 16];
701  buf[3] = 0;
702  putpacket (buf);
703}
704
705
706/*
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.
710 */
711
712
713static void
714handle_exception (registers)
715     unsigned long *registers;
716{
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;
724
725/* First, we must force all of the windows to be spilled out */
726
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
743");
744
745  if (registers[PC] == (unsigned long)breakinst)
746    {
747      registers[PC] = registers[NPC];
748      registers[NPC] += 4;
749    }
750  sp = (unsigned long *)registers[SP];
751
752  dsr = (unsigned long)registers[DSR];
753  if (dsr & 0x3c)
754    {
755      tt = 255;
756    }
757  else
758    {
759      tt = (registers[TBR] >> 4) & 0xff;
760    }
761
762  /* reply to host that an exception has occurred */
763  sigval = computeSignal(tt);
764  ptr = remcomOutBuffer;
765
766  *ptr++ = 'T';
767  *ptr++ = hexchars[sigval >> 4];
768  *ptr++ = hexchars[sigval & 0xf];
769
770  *ptr++ = hexchars[PC >> 4];
771  *ptr++ = hexchars[PC & 0xf];
772  *ptr++ = ':';
773  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
774  *ptr++ = ';';
775
776  *ptr++ = hexchars[FP >> 4];
777  *ptr++ = hexchars[FP & 0xf];
778  *ptr++ = ':';
779  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
780  *ptr++ = ';';
781
782  *ptr++ = hexchars[SP >> 4];
783  *ptr++ = hexchars[SP & 0xf];
784  *ptr++ = ':';
785  ptr = mem2hex((char *)&sp, ptr, 4, 0);
786  *ptr++ = ';';
787
788  *ptr++ = hexchars[NPC >> 4];
789  *ptr++ = hexchars[NPC & 0xf];
790  *ptr++ = ':';
791  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
792  *ptr++ = ';';
793
794  *ptr++ = hexchars[O7 >> 4];
795  *ptr++ = hexchars[O7 & 0xf];
796  *ptr++ = ':';
797  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
798  *ptr++ = ';';
799
800  *ptr++ = 0;
801
802  putpacket(remcomOutBuffer);
803
804  __outbyte_hook = outbyte_stub;
805
806  while (1)
807    {
808      remcomOutBuffer[0] = 0;
809
810      getpacket(remcomInBuffer);
811      switch (remcomInBuffer[0])
812        {
813        case '?':
814          remcomOutBuffer[0] = 'S';
815          remcomOutBuffer[1] = hexchars[sigval >> 4];
816          remcomOutBuffer[2] = hexchars[sigval & 0xf];
817          remcomOutBuffer[3] = 0;
818          break;
819
820        case 'd':
821                                /* toggle debug flag */
822          break;
823
824        case 'g':               /* return the value of the CPU registers */
825          {
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 */
836          }
837          break;
838
839        case 'G':          /* set the value of the CPU registers - return OK */
840          {
841            unsigned long *newsp, psr;
842
843            psr = registers[PSR];
844
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 */
852
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.  */
856
857            newsp = (unsigned long *)registers[SP];
858            if (sp != newsp)
859              sp = memcpy(newsp, sp, 16 * 4);
860
861            /* Don't allow CWP to be modified. */
862
863            if (psr != registers[PSR])
864              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
865
866            strcpy(remcomOutBuffer,"OK");
867          }
868          break;
869
870        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
871          /* Try to read %x,%x.  */
872
873          ptr = &remcomInBuffer[1];
874
875          if (hexToInt(&ptr, &addr)
876              && *ptr++ == ','
877              && hexToInt(&ptr, &length))
878            {
879              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
880                break;
881
882              strcpy (remcomOutBuffer, "E03");
883            }
884          else
885            strcpy(remcomOutBuffer,"E01");
886          break;
887
888        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
889          /* Try to read '%x,%x:'.  */
890
891          ptr = &remcomInBuffer[1];
892
893          if (hexToInt(&ptr, &addr)
894              && *ptr++ == ','
895              && hexToInt(&ptr, &length)
896              && *ptr++ == ':')
897            {
898              if (hex2mem(ptr, (char *)addr, length, 1))
899                strcpy(remcomOutBuffer, "OK");
900              else
901                strcpy(remcomOutBuffer, "E03");
902            }
903          else
904            strcpy(remcomOutBuffer, "E02");
905          break;
906
907        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
908          /* try to read optional parameter, pc unchanged if no parm */
909
910          ptr = &remcomInBuffer[1];
911          if (hexToInt(&ptr, &addr))
912            {
913              registers[PC] = addr;
914              registers[NPC] = addr + 4;
915            }
916
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.
920 */
921
922          flush_i_cache();
923          return;
924
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;
937
938#if 0
939Disabled until we can unscrew this properly
940
941        case 'b':         /* bBB...  Set baud rate to BB... */
942          {
943            int baudrate;
944            extern void set_timer_3();
945
946            ptr = &remcomInBuffer[1];
947            if (!hexToInt(&ptr, &baudrate))
948              {
949                strcpy(remcomOutBuffer,"B01");
950                break;
951              }
952
953            /* Convert baud rate to uart clock divider */
954            switch (baudrate)
955              {
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;
968              }
969
970            putpacket("OK");    /* Ack before changing speed */
971            set_timer_3(baudrate); /* Set it */
972          }
973x1:       break;
974#endif
975        }                       /* switch */
976
977      /* reply to the request */
978      putpacket(remcomOutBuffer);
979    }
980}
981
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. */
986
987void
988breakpoint()
989{
990  if (!initialized)
991    return;
992
993  asm(" .globl " STRINGSYM(breakinst) "
994
995        " STRINGSYM(breakinst) ": ta 1
996      ");
997}
998
999static void
1000hw_breakpoint()
1001{
1002  asm("
1003      ta 127
1004      ");
1005}
Note: See TracBrowser for help on using the repository browser.