1 /****************************************************************************
3 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
13 ****************************************************************************/
15 /****************************************************************************
16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
18 * Module name: remcom.c $
20 * Date: 91/03/09 12:29:49 $
21 * Contributor: Lake Stevens Instrument Division$
23 * Description: low level support for gdb debugger. $
25 * Considerations: only works on target hardware $
27 * Written by: Glenn Engel $
28 * ModuleState: Experimental $
32 * Modified for SPARC by Stu Grossman, Cygnus Support.
33 * Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware
34 * breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support.
36 * This code has been extensively tested on the Fujitsu SPARClite demo board.
38 * To enable debugger support, two things need to happen. One, a
39 * call to set_debug_traps() is necessary in order to allow any breakpoints
40 * or error conditions to be properly intercepted and reported to gdb.
41 * Two, a breakpoint needs to be generated to begin communication. This
42 * is most easily accomplished by a call to breakpoint(). Breakpoint()
43 * simulates a breakpoint by executing a trap #1.
47 * The following gdb commands are supported:
49 * command function Return value
51 * g return the value of the CPU registers hex data or ENN
52 * G set the value of the CPU registers OK or ENN
54 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
55 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
57 * c Resume at current address SNN ( signal NN)
58 * cAA..AA Continue at address AA..AA SNN
60 * s Step one instruction SNN
61 * sAA..AA Step one instruction from AA..AA SNN
65 * ? What was the last sigval ? SNN (signal NN)
67 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
70 * All commands and responses are sent with a packet which includes a
71 * checksum. A packet consists of
73 * $<packet info>#<checksum>.
76 * <packet info> :: <characters representing the command or response>
77 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
79 * When a packet is received, it is first acknowledged with either '+' or '-'.
80 * '+' indicates a successful transfer. '-' indicates a failed transfer.
85 * $m0,10#2a +$00010203040506070809101112131415#42
87 ****************************************************************************/
91 #include <sparclite.h>
93 /************************************************************************
95 * external low-level support routines
98 extern putDebugChar(); /* write a single character */
99 extern getDebugChar(); /* read and return a single char */
101 /************************************************************************/
102 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
103 /* at least NUMREGBYTES*2 are needed for register packets */
106 static int initialized
= 0; /* !0 means we've been initialized */
108 extern void breakinst();
109 static void hw_breakpoint();
110 static void set_mem_fault_trap();
111 static void get_in_break_mode();
113 static const char hexchars
[]="0123456789abcdef";
117 /* Number of bytes of registers. */
118 #define NUMREGBYTES (NUMREGS * 4)
119 enum regnames
{G0
, G1
, G2
, G3
, G4
, G5
, G6
, G7
,
120 O0
, O1
, O2
, O3
, O4
, O5
, SP
, O7
,
121 L0
, L1
, L2
, L3
, L4
, L5
, L6
, L7
,
122 I0
, I1
, I2
, I3
, I4
, I5
, FP
, I7
,
124 F0
, F1
, F2
, F3
, F4
, F5
, F6
, F7
,
125 F8
, F9
, F10
, F11
, F12
, F13
, F14
, F15
,
126 F16
, F17
, F18
, F19
, F20
, F21
, F22
, F23
,
127 F24
, F25
, F26
, F27
, F28
, F29
, F30
, F31
,
128 Y
, PSR
, WIM
, TBR
, PC
, NPC
, FPSR
, CPSR
,
129 DIA1
, DIA2
, DDA1
, DDA2
, DDV1
, DDV2
, DCR
, DSR
};
131 /*************************** ASSEMBLY CODE MACROS *************************/
134 extern void trap_low();
137 .reserve trapstack, 1000 * 4, \"bss\", 8
148 ! This function is called when any SPARC trap (except window overflow or
149 ! underflow) occurs. It makes sure that the invalid register window is still
150 ! available before jumping into C code. It will also restore the world if you
151 ! return from handle_exception.
158 srl %l3, %l0, %l4 ! wim >> cwp
160 bne window_fine ! Branch if not in the invalid window
163 ! Handle window overflow
165 mov %g1, %l4 ! Save g1, we use it to hold the wim
166 srl %l3, 1, %g1 ! Rotate wim right
168 bg good_wim ! Branch if new wim is non-zero
171 ! At this point, we need to bring a 1 into the high order bit of the wim.
172 ! Since we don't want to make any assumptions about the number of register
173 ! windows, we figure it out dynamically so as to setup the wim correctly.
175 not %g1 ! Fill g1 with ones
176 mov %g1, %wim ! Fill the wim with ones
180 mov %wim, %g1 ! Read back the wim
181 inc %g1 ! Now g1 has 1 just to left of wim
182 srl %g1, 1, %g1 ! Now put 1 at top of wim
183 mov %g0, %wim ! Clear wim so that subsequent save
189 save %g0, %g0, %g0 ! Slip into next window
190 mov %g1, %wim ! Install the new wim
192 std %l0, [%sp + 0 * 4] ! save L & I registers
193 std %l2, [%sp + 2 * 4]
194 std %l4, [%sp + 4 * 4]
195 std %l6, [%sp + 6 * 4]
197 std %i0, [%sp + 8 * 4]
198 std %i2, [%sp + 10 * 4]
199 std %i4, [%sp + 12 * 4]
200 std %i6, [%sp + 14 * 4]
202 restore ! Go back to trap window.
203 mov %l4, %g1 ! Restore %g1
206 sethi %hi(in_trap_handler), %l4
207 ld [%lo(in_trap_handler) + %l4], %l5
212 set trapstack+1000*4, %sp ! Switch to trap stack
215 st %l5, [%lo(in_trap_handler) + %l4]
216 sub %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals
217 ! + hidden arg + arg spill
218 ! + doubleword alignment
219 ! + registers[72] local var
221 std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
222 std %g2, [%sp + (24 + 2) * 4]
223 std %g4, [%sp + (24 + 4) * 4]
224 std %g6, [%sp + (24 + 6) * 4]
226 std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
227 std %i2, [%sp + (24 + 10) * 4]
228 std %i4, [%sp + (24 + 12) * 4]
229 std %i6, [%sp + (24 + 14) * 4]
233 st %l4, [%sp + (24 + 64) * 4] ! Y
234 st %l0, [%sp + (24 + 65) * 4] ! PSR
235 st %l3, [%sp + (24 + 66) * 4] ! WIM
236 st %l5, [%sp + (24 + 67) * 4] ! TBR
237 st %l1, [%sp + (24 + 68) * 4] ! PC
238 st %l2, [%sp + (24 + 69) * 4] ! NPC
241 mov %l4, %psr ! Turn on traps, disable interrupts
247 btst %l1, %l0 ! FP enabled?
251 ! Must save fsr first, to flush the FQ. This may cause a deferred fp trap, so
252 ! traps must be enabled to allow the trap handler to clean things up.
254 st %fsr, [%sp + (24 + 70) * 4]
256 std %f0, [%sp + (24 + 32) * 4]
257 std %f2, [%sp + (24 + 34) * 4]
258 std %f4, [%sp + (24 + 36) * 4]
259 std %f6, [%sp + (24 + 38) * 4]
260 std %f8, [%sp + (24 + 40) * 4]
261 std %f10, [%sp + (24 + 42) * 4]
262 std %f12, [%sp + (24 + 44) * 4]
263 std %f14, [%sp + (24 + 46) * 4]
264 std %f16, [%sp + (24 + 48) * 4]
265 std %f18, [%sp + (24 + 50) * 4]
266 std %f20, [%sp + (24 + 52) * 4]
267 std %f22, [%sp + (24 + 54) * 4]
268 std %f24, [%sp + (24 + 56) * 4]
269 std %f26, [%sp + (24 + 58) * 4]
270 std %f28, [%sp + (24 + 60) * 4]
271 std %f30, [%sp + (24 + 62) * 4]
274 call _get_in_break_mode
279 std %l4, [%sp + (24 + 72) * 4] ! DIA1, debug instr addr 1
280 ! DIA2, debug instr addr 2
283 std %l4, [%sp + (24 + 74) * 4] ! DDA1, debug data addr 1
284 ! DDA2, debug data addr 2
287 std %l4, [%sp + (24 + 76) * 4] ! DDV1, debug data val 1
288 ! DDV2, debug data val 2
291 std %l4, [%sp + (24 + 78) * 4] ! DCR, debug control reg
292 ! DSR, debug status reg
294 call _handle_exception
295 add %sp, 24 * 4, %o0 ! Pass address of registers
297 ! Reload all of the registers that aren't on the stack
299 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
300 ldd [%sp + (24 + 2) * 4], %g2
301 ldd [%sp + (24 + 4) * 4], %g4
302 ldd [%sp + (24 + 6) * 4], %g6
304 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
305 ldd [%sp + (24 + 10) * 4], %i2
306 ldd [%sp + (24 + 12) * 4], %i4
307 ldd [%sp + (24 + 14) * 4], %i6
310 ldd [%sp + (24 + 72) * 4], %l4
311 stda %l4, [%l2]0x1 ! DIA1, debug instr addr 1
312 ! DIA2, debug instr addr 2
314 ldd [%sp + (24 + 74) * 4], %l4
315 stda %l4, [%l2]0x1 ! DDA1, debug data addr 1
316 ! DDA2, debug data addr 2
318 ldd [%sp + (24 + 76) * 4], %l4
319 stda %l4, [%l2]0x1 ! DDV1, debug data value 1
320 ! DDV2, debug data val 2
322 ldd [%sp + (24 + 78) * 4], %l4
324 stda %l4, [%l2]0x1 ! DCR, debug control reg
325 ! DSR, debug control reg
328 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
329 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
332 btst %l5, %l1 ! FP enabled?
336 ldd [%sp + (24 + 32) * 4], %f0
337 ldd [%sp + (24 + 34) * 4], %f2
338 ldd [%sp + (24 + 36) * 4], %f4
339 ldd [%sp + (24 + 38) * 4], %f6
340 ldd [%sp + (24 + 40) * 4], %f8
341 ldd [%sp + (24 + 42) * 4], %f10
342 ldd [%sp + (24 + 44) * 4], %f12
343 ldd [%sp + (24 + 46) * 4], %f14
344 ldd [%sp + (24 + 48) * 4], %f16
345 ldd [%sp + (24 + 50) * 4], %f18
346 ldd [%sp + (24 + 52) * 4], %f20
347 ldd [%sp + (24 + 54) * 4], %f22
348 ldd [%sp + (24 + 56) * 4], %f24
349 ldd [%sp + (24 + 58) * 4], %f26
350 ldd [%sp + (24 + 60) * 4], %f28
351 ldd [%sp + (24 + 62) * 4], %f30
353 ld [%sp + (24 + 70) * 4], %fsr
356 restore ! Ensure that previous window is valid
357 save %g0, %g0, %g0 ! by causing a window_underflow trap
360 mov %l1, %psr ! Make sure that traps are disabled
362 sethi %hi(in_trap_handler), %l4
363 ld [%lo(in_trap_handler) + %l4], %l5
365 st %l5, [%lo(in_trap_handler) + %l4]
367 jmpl %l2, %g0 ! Restore old PC
368 rett %l3 ! Restore old nPC
371 /* Convert ch from a hex digit to an int */
377 if (ch
>= 'a' && ch
<= 'f')
379 if (ch
>= '0' && ch
<= '9')
381 if (ch
>= 'A' && ch
<= 'F')
386 /* scan for the sequence $<data>#<checksum> */
392 unsigned char checksum
;
393 unsigned char xmitcsum
;
400 /* wait around for the start character, ignore all other characters */
401 while ((ch
= (getDebugChar() & 0x7f)) != '$') ;
408 /* now, read until a # or end of buffer is found */
409 while (count
< BUFMAX
)
411 ch
= getDebugChar() & 0x7f;
414 checksum
= checksum
+ ch
;
426 xmitcsum
= hex(getDebugChar() & 0x7f) << 4;
427 xmitcsum
|= hex(getDebugChar() & 0x7f);
429 /* Humans shouldn't have to figure out checksums to type to it. */
433 if (checksum
!= xmitcsum
)
434 putDebugChar('-'); /* failed checksum */
437 putDebugChar('+'); /* successful transfer */
438 /* if a sequence char is present, reply the sequence ID */
439 if (buffer
[2] == ':')
441 putDebugChar(buffer
[0]);
442 putDebugChar(buffer
[1]);
443 /* remove sequence chars from buffer */
444 count
= strlen(buffer
);
445 for (i
=3; i
<= count
; i
++)
446 buffer
[i
-3] = buffer
[i
];
451 while (checksum
!= xmitcsum
);
454 /* send the packet in buffer. */
458 unsigned char *buffer
;
460 unsigned char checksum
;
464 /* $<packet info>#<checksum>. */
471 while (ch
= buffer
[count
])
473 if (! putDebugChar(ch
))
480 putDebugChar(hexchars
[checksum
>> 4]);
481 putDebugChar(hexchars
[checksum
& 0xf]);
484 while ((getDebugChar() & 0x7f) != '+');
487 static char remcomInBuffer
[BUFMAX
];
488 static char remcomOutBuffer
[BUFMAX
];
490 /* Indicate to caller of mem2hex or hex2mem that there has been an
492 static volatile int mem_err
= 0;
494 /* Convert the memory pointed to by mem into hex, placing result in buf.
495 * Return a pointer to the last char put in buf (null), in case of mem fault,
497 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
498 * a 0, else treat a fault like any other fault in the stub.
501 static unsigned char *
502 mem2hex(mem
, buf
, count
, may_fault
)
510 set_mem_fault_trap(may_fault
);
517 *buf
++ = hexchars
[ch
>> 4];
518 *buf
++ = hexchars
[ch
& 0xf];
523 set_mem_fault_trap(0);
528 /* convert the hex array pointed to by buf into binary to be placed in mem
529 * return a pointer to the character AFTER the last byte written */
532 hex2mem(buf
, mem
, count
, may_fault
)
541 set_mem_fault_trap(may_fault
);
543 for (i
=0; i
<count
; i
++)
545 ch
= hex(*buf
++) << 4;
552 set_mem_fault_trap(0);
557 /* This table contains the mapping between SPARC hardware trap types, and
558 signals, which are primarily what GDB understands. It also indicates
559 which hardware traps we need to commandeer when initializing the stub. */
561 static struct hard_trap_info
563 unsigned char tt
; /* Trap type code for SPARClite */
564 unsigned char signo
; /* Signal that we map this trap into */
565 } hard_trap_info
[] = {
566 {0x01, SIGSEGV
}, /* instruction access error */
567 {0x02, SIGILL
}, /* privileged instruction */
568 {0x03, SIGILL
}, /* illegal instruction */
569 {0x04, SIGEMT
}, /* fp disabled */
570 {0x07, SIGBUS
}, /* mem address not aligned */
571 {0x09, SIGSEGV
}, /* data access exception */
572 {0x0a, SIGEMT
}, /* tag overflow */
573 {0x20, SIGBUS
}, /* r register access error */
574 {0x21, SIGBUS
}, /* instruction access error */
575 {0x24, SIGEMT
}, /* cp disabled */
576 {0x29, SIGBUS
}, /* data access error */
577 {0x2a, SIGFPE
}, /* divide by zero */
578 {0x2b, SIGBUS
}, /* data store error */
579 {0x80+1, SIGTRAP
}, /* ta 1 - normal breakpoint instruction */
580 {0xff, SIGTRAP
}, /* hardware breakpoint */
581 {0, 0} /* Must be last */
584 /* Set up exception handlers for tracing and breakpoints */
589 struct hard_trap_info
*ht
;
591 /* Only setup fp traps if the FP is disabled. */
593 for (ht
= hard_trap_info
;
594 ht
->tt
!= 0 && ht
->signo
!= 0;
596 if (ht
->tt
!= 4 || ! (read_psr () & 0x1000))
597 exceptionHandler(ht
->tt
, trap_low
);
599 /* In case GDB is started before us, ack any packets (presumably
600 "$?#xx") sitting there. */
608 ! Trap handler for memory errors. This just sets mem_err to be non-zero. It
609 ! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
610 ! 0 would ever contain code that could mem fault. This routine will skip
611 ! past the faulting instruction after setting mem_err.
617 sethi %hi(_mem_err), %l0
618 st %l1, [%l0 + %lo(_mem_err)]
624 set_mem_fault_trap(enable
)
627 extern void fltr_set_mem_err();
631 exceptionHandler(9, fltr_set_mem_err
);
633 exceptionHandler(9, trap_low
);
640 _dummy_hw_breakpoint:
650 extern void dummy_hw_breakpoint();
652 exceptionHandler (255, dummy_hw_breakpoint
);
654 write_asi (1, 0xff10, 0);
656 exceptionHandler (255, trap_low
);
659 /* Convert the SPARC hardware trap type code to a unix signal number. */
665 struct hard_trap_info
*ht
;
667 for (ht
= hard_trap_info
; ht
->tt
&& ht
->signo
; ht
++)
671 return SIGHUP
; /* default for things we don't know about */
675 * While we find nice hex chars, build an int.
676 * Return number of chars processed.
680 hexToInt(char **ptr
, int *intValue
)
689 hexValue
= hex(**ptr
);
693 *intValue
= (*intValue
<< 4) | hexValue
;
703 * This function does all command procesing for interfacing to gdb. It
704 * returns 1 if you should skip the instruction at the trap address, 0
710 handle_exception (registers
)
711 unsigned long *registers
;
713 int tt
; /* Trap type */
721 /* First, we must force all of the windows to be spilled out */
723 asm(" save %sp, -64, %sp
741 if (registers
[PC
] == (unsigned long)breakinst
)
743 registers
[PC
] = registers
[NPC
];
746 sp
= (unsigned long *)registers
[SP
];
748 dsr
= (unsigned long)registers
[DSR
];
752 tt
= (registers
[TBR
] >> 4) & 0xff;
754 /* reply to host that an exception has occurred */
755 sigval
= computeSignal(tt
);
756 ptr
= remcomOutBuffer
;
759 *ptr
++ = hexchars
[sigval
>> 4];
760 *ptr
++ = hexchars
[sigval
& 0xf];
762 *ptr
++ = hexchars
[PC
>> 4];
763 *ptr
++ = hexchars
[PC
& 0xf];
765 ptr
= mem2hex((char *)®isters
[PC
], ptr
, 4, 0);
768 *ptr
++ = hexchars
[FP
>> 4];
769 *ptr
++ = hexchars
[FP
& 0xf];
771 ptr
= mem2hex(sp
+ 8 + 6, ptr
, 4, 0); /* FP */
774 *ptr
++ = hexchars
[SP
>> 4];
775 *ptr
++ = hexchars
[SP
& 0xf];
777 ptr
= mem2hex((char *)&sp
, ptr
, 4, 0);
780 *ptr
++ = hexchars
[NPC
>> 4];
781 *ptr
++ = hexchars
[NPC
& 0xf];
783 ptr
= mem2hex((char *)®isters
[NPC
], ptr
, 4, 0);
786 *ptr
++ = hexchars
[O7
>> 4];
787 *ptr
++ = hexchars
[O7
& 0xf];
789 ptr
= mem2hex((char *)®isters
[O7
], ptr
, 4, 0);
794 putpacket(remcomOutBuffer
);
798 remcomOutBuffer
[0] = 0;
800 getpacket(remcomInBuffer
);
801 switch (remcomInBuffer
[0])
804 remcomOutBuffer
[0] = 'S';
805 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
806 remcomOutBuffer
[2] = hexchars
[sigval
& 0xf];
807 remcomOutBuffer
[3] = 0;
811 /* toggle debug flag */
814 case 'g': /* return the value of the CPU registers */
815 memcpy (®isters
[L0
], sp
, 16 * 4); /* Copy L & I regs from stack */
816 mem2hex ((char *)registers
, remcomOutBuffer
, NUMREGBYTES
, 0);
819 case 'G': /* Set the value of all registers */
820 case 'P': /* Set the value of one register */
822 unsigned long *newsp
, psr
;
824 psr
= registers
[PSR
];
826 ptr
= &remcomInBuffer
[1];
828 if (remcomInBuffer
[0] == 'P')
832 if (hexToInt (&ptr
, ®no
)
834 if (regno
>= L0
&& regno
<= I7
)
835 hex2mem (ptr
, sp
+ regno
- L0
, 4, 0);
837 hex2mem (ptr
, (char *)®isters
[regno
], 4, 0);
840 strcpy (remcomOutBuffer
, "P01");
846 hex2mem (ptr
, (char *)registers
, NUMREGBYTES
, 0);
847 memcpy (sp
, ®isters
[L0
], 16 * 4); /* Copy L & I regs to stack */
850 /* See if the stack pointer has moved. If so, then copy the saved
851 locals and ins to the new location. This keeps the window
852 overflow and underflow routines happy. */
854 newsp
= (unsigned long *)registers
[SP
];
856 sp
= memcpy(newsp
, sp
, 16 * 4);
858 /* Don't allow CWP to be modified. */
860 if (psr
!= registers
[PSR
])
861 registers
[PSR
] = (psr
& 0x1f) | (registers
[PSR
] & ~0x1f);
863 strcpy(remcomOutBuffer
,"OK");
867 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
868 /* Try to read %x,%x. */
870 ptr
= &remcomInBuffer
[1];
872 if (hexToInt(&ptr
, &addr
)
874 && hexToInt(&ptr
, &length
))
876 if (mem2hex((char *)addr
, remcomOutBuffer
, length
, 1))
879 strcpy (remcomOutBuffer
, "E03");
882 strcpy(remcomOutBuffer
,"E01");
885 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
886 /* Try to read '%x,%x:'. */
888 ptr
= &remcomInBuffer
[1];
890 if (hexToInt(&ptr
, &addr
)
892 && hexToInt(&ptr
, &length
)
895 if (hex2mem(ptr
, (char *)addr
, length
, 1))
896 strcpy(remcomOutBuffer
, "OK");
898 strcpy(remcomOutBuffer
, "E03");
901 strcpy(remcomOutBuffer
, "E02");
904 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
905 /* try to read optional parameter, pc unchanged if no parm */
907 ptr
= &remcomInBuffer
[1];
908 if (hexToInt(&ptr
, &addr
))
910 registers
[PC
] = addr
;
911 registers
[NPC
] = addr
+ 4;
914 /* Need to flush the instruction cache here, as we may have deposited a
915 breakpoint, and the icache probably has no way of knowing that a data ref to
916 some location may have changed something that is in the instruction cache.
922 /* kill the program */
923 case 'k' : /* do nothing */
926 case 't': /* Test feature */
927 asm (" std %f30,[%sp]");
930 case 'r': /* Reset */
936 Disabled until we can unscrew
this properly
938 case 'b': /* bBB... Set baud rate to BB... */
941 extern void set_timer_3();
943 ptr
= &remcomInBuffer
[1];
944 if (!hexToInt(&ptr
, &baudrate
))
946 strcpy(remcomOutBuffer
,"B01");
950 /* Convert baud rate to uart clock divider */
963 strcpy(remcomOutBuffer
,"B02");
967 putpacket("OK"); /* Ack before changing speed */
968 set_timer_3(baudrate
); /* Set it */
974 /* reply to the request */
975 putpacket(remcomOutBuffer
);
979 /* This function will generate a breakpoint exception. It is used at the
980 beginning of a program to sync up with a debugger and can be used
981 otherwise as a quick means to stop program execution and "break" into
990 asm(" .globl _breakinst