* stabs.texinfo: Express disapproval of 'D' symbol descriptor
[deliverable/binutils-gdb.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 restore ! Ensure that previous window is valid
224 save %g0, %g0, %g0 ! by causing a window_underflow trap
225
226 ! Reload all of the registers that aren't on the stack
227
228 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
229 ldd [%sp + (24 + 2) * 4], %g2
230 ldd [%sp + (24 + 4) * 4], %g4
231 ldd [%sp + (24 + 6) * 4], %g6
232
233 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
234 ldd [%sp + (24 + 10) * 4], %i2
235 ldd [%sp + (24 + 12) * 4], %i4
236 ldd [%sp + (24 + 14) * 4], %i6
237
238 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
239 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
240 mov %l0, %y
241 mov %l1, %psr ! Make sure that traps are disabled
242 ! for rett
243
244 sethi %hi(in_trap_handler), %l4
245 ld [%lo(in_trap_handler) + %l4], %l5
246 dec %l5
247 st %l5, [%lo(in_trap_handler) + %l4]
248
249 jmpl %l2, %g0 ! Restore old PC
250 rett %l3 ! Restore old nPC
251 ");
252
253 /* Convert ch from a hex digit to an int */
254
255 static int
256 hex(ch)
257 unsigned char ch;
258 {
259 if (ch >= 'a' && ch <= 'f')
260 return ch-'a'+10;
261 if (ch >= '0' && ch <= '9')
262 return ch-'0';
263 if (ch >= 'A' && ch <= 'F')
264 return ch-'A'+10;
265 return -1;
266 }
267
268 /* scan for the sequence $<data>#<checksum> */
269
270 static void
271 getpacket(buffer)
272 char *buffer;
273 {
274 unsigned char checksum;
275 unsigned char xmitcsum;
276 int i;
277 int count;
278 unsigned char ch;
279
280 do
281 {
282 /* wait around for the start character, ignore all other characters */
283 while ((ch = getDebugChar()) != '$') ;
284
285 checksum = 0;
286 xmitcsum = -1;
287
288 count = 0;
289
290 /* now, read until a # or end of buffer is found */
291 while (count < BUFMAX)
292 {
293 ch = getDebugChar();
294 if (ch == '#')
295 break;
296 checksum = checksum + ch;
297 buffer[count] = ch;
298 count = count + 1;
299 }
300
301 if (count >= BUFMAX)
302 continue;
303
304 buffer[count] = 0;
305
306 if (ch == '#')
307 {
308 xmitcsum = hex(getDebugChar()) << 4;
309 xmitcsum |= hex(getDebugChar());
310 #if 0
311 /* Humans shouldn't have to figure out checksums to type to it. */
312 putDebugChar ('+');
313 return;
314 #endif
315 if (checksum != xmitcsum)
316 putDebugChar('-'); /* failed checksum */
317 else
318 {
319 putDebugChar('+'); /* successful transfer */
320 /* if a sequence char is present, reply the sequence ID */
321 if (buffer[2] == ':')
322 {
323 putDebugChar(buffer[0]);
324 putDebugChar(buffer[1]);
325 /* remove sequence chars from buffer */
326 count = strlen(buffer);
327 for (i=3; i <= count; i++)
328 buffer[i-3] = buffer[i];
329 }
330 }
331 }
332 }
333 while (checksum != xmitcsum);
334 }
335
336 /* send the packet in buffer. */
337
338 static void
339 putpacket(buffer)
340 unsigned char *buffer;
341 {
342 unsigned char checksum;
343 int count;
344 unsigned char ch;
345
346 /* $<packet info>#<checksum>. */
347 do
348 {
349 putDebugChar('$');
350 checksum = 0;
351 count = 0;
352
353 while (ch = buffer[count])
354 {
355 if (! putDebugChar(ch))
356 return;
357 checksum += ch;
358 count += 1;
359 }
360
361 putDebugChar('#');
362 putDebugChar(hexchars[checksum >> 4]);
363 putDebugChar(hexchars[checksum & 0xf]);
364
365 }
366 while (getDebugChar() != '+');
367 }
368
369 static char remcomInBuffer[BUFMAX];
370 static char remcomOutBuffer[BUFMAX];
371
372 /* Indicate to caller of mem2hex or hex2mem that there has been an
373 error. */
374 static volatile int mem_err = 0;
375
376 /* Convert the memory pointed to by mem into hex, placing result in buf.
377 * Return a pointer to the last char put in buf (null), in case of mem fault,
378 * return 0.
379 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
380 * a 0, else treat a fault like any other fault in the stub.
381 */
382
383 static unsigned char *
384 mem2hex(mem, buf, count, may_fault)
385 unsigned char *mem;
386 unsigned char *buf;
387 int count;
388 int may_fault;
389 {
390 unsigned char ch;
391
392 set_mem_fault_trap(may_fault);
393
394 while (count-- > 0)
395 {
396 ch = *mem++;
397 if (mem_err)
398 return 0;
399 *buf++ = hexchars[ch >> 4];
400 *buf++ = hexchars[ch & 0xf];
401 }
402
403 *buf = 0;
404
405 set_mem_fault_trap(0);
406
407 return buf;
408 }
409
410 /* convert the hex array pointed to by buf into binary to be placed in mem
411 * return a pointer to the character AFTER the last byte written */
412
413 static char *
414 hex2mem(buf, mem, count, may_fault)
415 unsigned char *buf;
416 unsigned char *mem;
417 int count;
418 int may_fault;
419 {
420 int i;
421 unsigned char ch;
422
423 set_mem_fault_trap(may_fault);
424
425 for (i=0; i<count; i++)
426 {
427 ch = hex(*buf++) << 4;
428 ch |= hex(*buf++);
429 *mem++ = ch;
430 if (mem_err)
431 return 0;
432 }
433
434 set_mem_fault_trap(0);
435
436 return mem;
437 }
438
439 /* This table contains the mapping between SPARC hardware trap types, and
440 signals, which are primarily what GDB understands. It also indicates
441 which hardware traps we need to commandeer when initializing the stub. */
442
443 static struct hard_trap_info
444 {
445 unsigned char tt; /* Trap type code for SPARClite */
446 unsigned char signo; /* Signal that we map this trap into */
447 } hard_trap_info[] = {
448 {1, SIGSEGV}, /* instruction access error */
449 {2, SIGILL}, /* privileged instruction */
450 {3, SIGILL}, /* illegal instruction */
451 {4, SIGEMT}, /* fp disabled */
452 {36, SIGEMT}, /* cp disabled */
453 {7, SIGBUS}, /* mem address not aligned */
454 {9, SIGSEGV}, /* data access exception */
455 {10, SIGEMT}, /* tag overflow */
456 {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
457 {0, 0} /* Must be last */
458 };
459
460 /* Set up exception handlers for tracing and breakpoints */
461
462 void
463 set_debug_traps()
464 {
465 struct hard_trap_info *ht;
466
467 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
468 exceptionHandler(ht->tt, trap_low);
469
470 /* In case GDB is started before us, ack any packets (presumably
471 "$?#xx") sitting there. */
472
473 putDebugChar ('+');
474
475 initialized = 1;
476 }
477
478 asm ("
479 ! Trap handler for memory errors. This just sets mem_err to be non-zero. It
480 ! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
481 ! 0 would ever contain code that could mem fault. This routine will skip
482 ! past the faulting instruction after setting mem_err.
483
484 .text
485 .align 4
486
487 _fltr_set_mem_err:
488 sethi %hi(_mem_err), %l0
489 st %l1, [%l0 + %lo(_mem_err)]
490 jmpl %l2, %g0
491 rett %l2+4
492 ");
493
494 static void
495 set_mem_fault_trap(enable)
496 int enable;
497 {
498 extern void fltr_set_mem_err();
499 mem_err = 0;
500
501 if (enable)
502 exceptionHandler(9, fltr_set_mem_err);
503 else
504 exceptionHandler(9, trap_low);
505 }
506
507 /* Convert the SPARC hardware trap type code to a unix signal number. */
508
509 static int
510 computeSignal(tt)
511 int tt;
512 {
513 struct hard_trap_info *ht;
514
515 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
516 if (ht->tt == tt)
517 return ht->signo;
518
519 return SIGHUP; /* default for things we don't know about */
520 }
521
522 /*
523 * While we find nice hex chars, build an int.
524 * Return number of chars processed.
525 */
526
527 static int
528 hexToInt(char **ptr, int *intValue)
529 {
530 int numChars = 0;
531 int hexValue;
532
533 *intValue = 0;
534
535 while (**ptr)
536 {
537 hexValue = hex(**ptr);
538 if (hexValue < 0)
539 break;
540
541 *intValue = (*intValue << 4) | hexValue;
542 numChars ++;
543
544 (*ptr)++;
545 }
546
547 return (numChars);
548 }
549
550 /*
551 * This function does all command procesing for interfacing to gdb. It
552 * returns 1 if you should skip the instruction at the trap address, 0
553 * otherwise.
554 */
555
556 extern void breakinst();
557
558 static void
559 handle_exception (registers)
560 unsigned long *registers;
561 {
562 int tt; /* Trap type */
563 int sigval;
564 int addr;
565 int length;
566 char *ptr;
567 unsigned long *sp;
568
569 /* First, we must force all of the windows to be spilled out */
570
571 asm(" save %sp, -64, %sp
572 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 restore
580 restore
581 restore
582 restore
583 restore
584 restore
585 restore
586 restore
587 ");
588
589 if (registers[PC] == (unsigned long)breakinst)
590 {
591 registers[PC] = registers[NPC];
592 registers[NPC] += 4;
593 }
594
595 sp = (unsigned long *)registers[SP];
596
597 tt = (registers[TBR] >> 4) & 0xff;
598
599 /* reply to host that an exception has occurred */
600 sigval = computeSignal(tt);
601 ptr = remcomOutBuffer;
602
603 *ptr++ = 'T';
604 *ptr++ = hexchars[sigval >> 4];
605 *ptr++ = hexchars[sigval & 0xf];
606
607 *ptr++ = hexchars[PC >> 4];
608 *ptr++ = hexchars[PC & 0xf];
609 *ptr++ = ':';
610 ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
611 *ptr++ = ';';
612
613 *ptr++ = hexchars[FP >> 4];
614 *ptr++ = hexchars[FP & 0xf];
615 *ptr++ = ':';
616 ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
617 *ptr++ = ';';
618
619 *ptr++ = hexchars[SP >> 4];
620 *ptr++ = hexchars[SP & 0xf];
621 *ptr++ = ':';
622 ptr = mem2hex((char *)&sp, ptr, 4, 0);
623 *ptr++ = ';';
624
625 *ptr++ = hexchars[NPC >> 4];
626 *ptr++ = hexchars[NPC & 0xf];
627 *ptr++ = ':';
628 ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
629 *ptr++ = ';';
630
631 *ptr++ = hexchars[O7 >> 4];
632 *ptr++ = hexchars[O7 & 0xf];
633 *ptr++ = ':';
634 ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
635 *ptr++ = ';';
636
637 *ptr++ = 0;
638
639 putpacket(remcomOutBuffer);
640
641 while (1)
642 {
643 remcomOutBuffer[0] = 0;
644
645 getpacket(remcomInBuffer);
646 switch (remcomInBuffer[0])
647 {
648 case '?':
649 remcomOutBuffer[0] = 'S';
650 remcomOutBuffer[1] = hexchars[sigval >> 4];
651 remcomOutBuffer[2] = hexchars[sigval & 0xf];
652 remcomOutBuffer[3] = 0;
653 break;
654
655 case 'd':
656 /* toggle debug flag */
657 break;
658
659 case 'g': /* return the value of the CPU registers */
660 {
661 ptr = remcomOutBuffer;
662 ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
663 ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
664 memset(ptr, '0', 32 * 8); /* Floating point */
665 mem2hex((char *)&registers[Y],
666 ptr + 32 * 4 * 2,
667 8 * 4,
668 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
669 }
670 break;
671
672 case 'G': /* set the value of the CPU registers - return OK */
673 {
674 unsigned long *newsp, psr;
675
676 psr = registers[PSR];
677
678 ptr = &remcomInBuffer[1];
679 hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
680 hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
681 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
682 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
683
684 /* See if the stack pointer has moved. If so, then copy the saved
685 locals and ins to the new location. This keeps the window
686 overflow and underflow routines happy. */
687
688 newsp = (unsigned long *)registers[SP];
689 if (sp != newsp)
690 sp = memcpy(newsp, sp, 16 * 4);
691
692 /* Don't allow CWP to be modified. */
693
694 if (psr != registers[PSR])
695 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
696
697 strcpy(remcomOutBuffer,"OK");
698 }
699 break;
700
701 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
702 /* Try to read %x,%x. */
703
704 ptr = &remcomInBuffer[1];
705
706 if (hexToInt(&ptr, &addr)
707 && *ptr++ == ','
708 && hexToInt(&ptr, &length))
709 {
710 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
711 break;
712
713 strcpy (remcomOutBuffer, "E03");
714 }
715 else
716 strcpy(remcomOutBuffer,"E01");
717 break;
718
719 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
720 /* Try to read '%x,%x:'. */
721
722 ptr = &remcomInBuffer[1];
723
724 if (hexToInt(&ptr, &addr)
725 && *ptr++ == ','
726 && hexToInt(&ptr, &length)
727 && *ptr++ == ':')
728 {
729 if (hex2mem(ptr, (char *)addr, length, 1))
730 strcpy(remcomOutBuffer, "OK");
731 else
732 strcpy(remcomOutBuffer, "E03");
733 }
734 else
735 strcpy(remcomOutBuffer, "E02");
736 break;
737
738 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
739 /* try to read optional parameter, pc unchanged if no parm */
740
741 ptr = &remcomInBuffer[1];
742 if (hexToInt(&ptr, &addr))
743 {
744 registers[PC] = addr;
745 registers[NPC] = addr + 4;
746 }
747
748 /* Need to flush the instruction cache here, as we may have deposited a
749 breakpoint, and the icache probably has no way of knowing that a data ref to
750 some location may have changed something that is in the instruction cache.
751 */
752
753 flush_i_cache();
754 return;
755
756 /* kill the program */
757 case 'k' : /* do nothing */
758 break;
759 #if 0
760 case 't': /* Test feature */
761 asm (" std %f31,[%sp]");
762 break;
763 #endif
764 case 'r': /* Reset */
765 asm ("call 0
766 nop ");
767 break;
768
769 #if 0
770 Disabled until we can unscrew this properly
771
772 case 'b': /* bBB... Set baud rate to BB... */
773 {
774 int baudrate;
775 extern void set_timer_3();
776
777 ptr = &remcomInBuffer[1];
778 if (!hexToInt(&ptr, &baudrate))
779 {
780 strcpy(remcomOutBuffer,"B01");
781 break;
782 }
783
784 /* Convert baud rate to uart clock divider */
785 switch (baudrate)
786 {
787 case 38400:
788 baudrate = 16;
789 break;
790 case 19200:
791 baudrate = 33;
792 break;
793 case 9600:
794 baudrate = 65;
795 break;
796 default:
797 strcpy(remcomOutBuffer,"B02");
798 goto x1;
799 }
800
801 putpacket("OK"); /* Ack before changing speed */
802 set_timer_3(baudrate); /* Set it */
803 }
804 x1: break;
805 #endif
806 } /* switch */
807
808 /* reply to the request */
809 putpacket(remcomOutBuffer);
810 }
811 }
812
813 /* This function will generate a breakpoint exception. It is used at the
814 beginning of a program to sync up with a debugger and can be used
815 otherwise as a quick means to stop program execution and "break" into
816 the debugger. */
817
818 void
819 breakpoint()
820 {
821 if (!initialized)
822 return;
823
824 asm(" .globl _breakinst
825
826 _breakinst: ta 1
827 ");
828 }
This page took 0.062401 seconds and 4 git commands to generate.