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