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