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

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

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

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