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 void putDebugChar (int c
); /* write a single character */
99 extern int getDebugChar (void); /* 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 set_mem_fault_trap (int enable
);
110 static void get_in_break_mode (void);
112 static const char hexchars
[]="0123456789abcdef";
116 /* Number of bytes of registers. */
117 #define NUMREGBYTES (NUMREGS * 4)
118 enum regnames
{G0
, G1
, G2
, G3
, G4
, G5
, G6
, G7
,
119 O0
, O1
, O2
, O3
, O4
, O5
, SP
, O7
,
120 L0
, L1
, L2
, L3
, L4
, L5
, L6
, L7
,
121 I0
, I1
, I2
, I3
, I4
, I5
, FP
, I7
,
123 F0
, F1
, F2
, F3
, F4
, F5
, F6
, F7
,
124 F8
, F9
, F10
, F11
, F12
, F13
, F14
, F15
,
125 F16
, F17
, F18
, F19
, F20
, F21
, F22
, F23
,
126 F24
, F25
, F26
, F27
, F28
, F29
, F30
, F31
,
127 Y
, PSR
, WIM
, TBR
, PC
, NPC
, FPSR
, CPSR
,
128 DIA1
, DIA2
, DDA1
, DDA2
, DDV1
, DDV2
, DCR
, DSR
};
130 /*************************** ASSEMBLY CODE MACROS *************************/
133 extern void trap_low();
135 /* Create private copies of common functions used by the stub. This prevents
136 nasty interactions between app code and the stub (for instance if user steps
137 into strlen, etc..) */
140 strlen (const char *s
)
144 while (*s1
++ != '\000');
150 strcpy (char *dst
, const char *src
)
154 while ((*dst
++ = *src
++) != '\000');
160 memcpy (void *vdst
, const void *vsrc
, int n
)
163 const char *src
= vsrc
;
173 .reserve trapstack, 1000 * 4, \"bss\", 8
184 ! This function is called when any SPARC trap (except window overflow or
185 ! underflow) occurs. It makes sure that the invalid register window is still
186 ! available before jumping into C code. It will also restore the world if you
187 ! return from handle_exception.
189 ! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly.
190 ! Register usage throughout the routine is as follows:
196 ! l4 - scratch and y reg
197 ! l5 - scratch and tbr
206 srl %l3, %l0, %l4 ! wim >> cwp
208 bne window_fine ! Branch if not in the invalid window
211 ! Handle window overflow
213 mov %g1, %l4 ! Save g1, we use it to hold the wim
214 srl %l3, 1, %g1 ! Rotate wim right
216 bg good_wim ! Branch if new wim is non-zero
219 ! At this point, we need to bring a 1 into the high order bit of the wim.
220 ! Since we don't want to make any assumptions about the number of register
221 ! windows, we figure it out dynamically so as to setup the wim correctly.
223 not %g1 ! Fill g1 with ones
224 mov %g1, %wim ! Fill the wim with ones
228 mov %wim, %g1 ! Read back the wim
229 inc %g1 ! Now g1 has 1 just to left of wim
230 srl %g1, 1, %g1 ! Now put 1 at top of wim
231 mov %g0, %wim ! Clear wim so that subsequent save
237 save %g0, %g0, %g0 ! Slip into next window
238 mov %g1, %wim ! Install the new wim
240 std %l0, [%sp + 0 * 4] ! save L & I registers
241 std %l2, [%sp + 2 * 4]
242 std %l4, [%sp + 4 * 4]
243 std %l6, [%sp + 6 * 4]
245 std %i0, [%sp + 8 * 4]
246 std %i2, [%sp + 10 * 4]
247 std %i4, [%sp + 12 * 4]
248 std %i6, [%sp + 14 * 4]
250 restore ! Go back to trap window.
251 mov %l4, %g1 ! Restore %g1
254 sethi %hi(in_trap_handler), %l4
255 ld [%lo(in_trap_handler) + %l4], %l5
260 set trapstack+1000*4, %sp ! Switch to trap stack
263 st %l5, [%lo(in_trap_handler) + %l4]
264 sub %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals
265 ! + hidden arg + arg spill
266 ! + doubleword alignment
267 ! + registers[72] local var
269 std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
270 std %g2, [%sp + (24 + 2) * 4]
271 std %g4, [%sp + (24 + 4) * 4]
272 std %g6, [%sp + (24 + 6) * 4]
274 std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
275 std %i2, [%sp + (24 + 10) * 4]
276 std %i4, [%sp + (24 + 12) * 4]
277 std %i6, [%sp + (24 + 14) * 4]
281 st %l4, [%sp + (24 + 64) * 4] ! Y
282 st %l0, [%sp + (24 + 65) * 4] ! PSR
283 st %l3, [%sp + (24 + 66) * 4] ! WIM
284 st %l5, [%sp + (24 + 67) * 4] ! TBR
285 st %l1, [%sp + (24 + 68) * 4] ! PC
286 st %l2, [%sp + (24 + 69) * 4] ! NPC
289 mov %l4, %psr ! Turn on traps, disable interrupts
292 btst %l1, %l0 ! FP enabled?
296 ! Must save fsr first, to flush the FQ. This may cause a deferred fp trap, so
297 ! traps must be enabled to allow the trap handler to clean things up.
299 st %fsr, [%sp + (24 + 70) * 4]
301 std %f0, [%sp + (24 + 32) * 4]
302 std %f2, [%sp + (24 + 34) * 4]
303 std %f4, [%sp + (24 + 36) * 4]
304 std %f6, [%sp + (24 + 38) * 4]
305 std %f8, [%sp + (24 + 40) * 4]
306 std %f10, [%sp + (24 + 42) * 4]
307 std %f12, [%sp + (24 + 44) * 4]
308 std %f14, [%sp + (24 + 46) * 4]
309 std %f16, [%sp + (24 + 48) * 4]
310 std %f18, [%sp + (24 + 50) * 4]
311 std %f20, [%sp + (24 + 52) * 4]
312 std %f22, [%sp + (24 + 54) * 4]
313 std %f24, [%sp + (24 + 56) * 4]
314 std %f26, [%sp + (24 + 58) * 4]
315 std %f28, [%sp + (24 + 60) * 4]
316 std %f30, [%sp + (24 + 62) * 4]
319 call _handle_exception
320 add %sp, 24 * 4, %o0 ! Pass address of registers
322 ! Reload all of the registers that aren't on the stack
324 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
325 ldd [%sp + (24 + 2) * 4], %g2
326 ldd [%sp + (24 + 4) * 4], %g4
327 ldd [%sp + (24 + 6) * 4], %g6
329 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
330 ldd [%sp + (24 + 10) * 4], %i2
331 ldd [%sp + (24 + 12) * 4], %i4
332 ldd [%sp + (24 + 14) * 4], %i6
335 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
336 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
339 btst %l5, %l1 ! FP enabled?
343 ldd [%sp + (24 + 32) * 4], %f0
344 ldd [%sp + (24 + 34) * 4], %f2
345 ldd [%sp + (24 + 36) * 4], %f4
346 ldd [%sp + (24 + 38) * 4], %f6
347 ldd [%sp + (24 + 40) * 4], %f8
348 ldd [%sp + (24 + 42) * 4], %f10
349 ldd [%sp + (24 + 44) * 4], %f12
350 ldd [%sp + (24 + 46) * 4], %f14
351 ldd [%sp + (24 + 48) * 4], %f16
352 ldd [%sp + (24 + 50) * 4], %f18
353 ldd [%sp + (24 + 52) * 4], %f20
354 ldd [%sp + (24 + 54) * 4], %f22
355 ldd [%sp + (24 + 56) * 4], %f24
356 ldd [%sp + (24 + 58) * 4], %f26
357 ldd [%sp + (24 + 60) * 4], %f28
358 ldd [%sp + (24 + 62) * 4], %f30
360 ld [%sp + (24 + 70) * 4], %fsr
363 restore ! Ensure that previous window is valid
364 save %g0, %g0, %g0 ! by causing a window_underflow trap
367 mov %l1, %psr ! Make sure that traps are disabled
369 sethi %hi(in_trap_handler), %l4
370 ld [%lo(in_trap_handler) + %l4], %l5
372 st %l5, [%lo(in_trap_handler) + %l4]
374 jmpl %l2, %g0 ! Restore old PC
375 rett %l3 ! Restore old nPC
378 /* Convert ch from a hex digit to an int */
384 if (ch
>= 'a' && ch
<= 'f')
386 if (ch
>= '0' && ch
<= '9')
388 if (ch
>= 'A' && ch
<= 'F')
393 /* scan for the sequence $<data>#<checksum> */
399 unsigned char checksum
;
400 unsigned char xmitcsum
;
407 /* wait around for the start character, ignore all other characters */
408 while ((ch
= (getDebugChar() & 0x7f)) != '$') ;
415 /* now, read until a # or end of buffer is found */
416 while (count
< BUFMAX
)
418 ch
= getDebugChar() & 0x7f;
421 checksum
= checksum
+ ch
;
433 xmitcsum
= hex(getDebugChar() & 0x7f) << 4;
434 xmitcsum
|= hex(getDebugChar() & 0x7f);
436 /* Humans shouldn't have to figure out checksums to type to it. */
440 if (checksum
!= xmitcsum
)
441 putDebugChar('-'); /* failed checksum */
444 putDebugChar('+'); /* successful transfer */
445 /* if a sequence char is present, reply the sequence ID */
446 if (buffer
[2] == ':')
448 putDebugChar(buffer
[0]);
449 putDebugChar(buffer
[1]);
450 /* remove sequence chars from buffer */
451 count
= strlen(buffer
);
452 for (i
=3; i
<= count
; i
++)
453 buffer
[i
-3] = buffer
[i
];
458 while (checksum
!= xmitcsum
);
461 /* send the packet in buffer. */
465 unsigned char *buffer
;
467 unsigned char checksum
;
471 /* $<packet info>#<checksum>. */
478 while (ch
= buffer
[count
])
486 putDebugChar(hexchars
[checksum
>> 4]);
487 putDebugChar(hexchars
[checksum
& 0xf]);
490 while ((getDebugChar() & 0x7f) != '+');
493 static char remcomInBuffer
[BUFMAX
];
494 static char remcomOutBuffer
[BUFMAX
];
496 /* Indicate to caller of mem2hex or hex2mem that there has been an
498 static volatile int mem_err
= 0;
500 /* Convert the memory pointed to by mem into hex, placing result in buf.
501 * Return a pointer to the last char put in buf (null), in case of mem fault,
503 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
504 * a 0, else treat a fault like any other fault in the stub.
507 static unsigned char *
508 mem2hex(mem
, buf
, count
, may_fault
)
516 set_mem_fault_trap(may_fault
);
523 *buf
++ = hexchars
[ch
>> 4];
524 *buf
++ = hexchars
[ch
& 0xf];
529 set_mem_fault_trap(0);
534 /* convert the hex array pointed to by buf into binary to be placed in mem
535 * return a pointer to the character AFTER the last byte written */
538 hex2mem(buf
, mem
, count
, may_fault
)
547 set_mem_fault_trap(may_fault
);
549 for (i
=0; i
<count
; i
++)
551 ch
= hex(*buf
++) << 4;
558 set_mem_fault_trap(0);
563 /* This table contains the mapping between SPARC hardware trap types, and
564 signals, which are primarily what GDB understands. It also indicates
565 which hardware traps we need to commandeer when initializing the stub. */
567 static struct hard_trap_info
569 unsigned char tt
; /* Trap type code for SPARClite */
570 unsigned char signo
; /* Signal that we map this trap into */
571 } hard_trap_info
[] = {
572 {0x01, SIGSEGV
}, /* instruction access error */
573 {0x02, SIGILL
}, /* privileged instruction */
574 {0x03, SIGILL
}, /* illegal instruction */
575 {0x04, SIGEMT
}, /* fp disabled */
576 {0x07, SIGBUS
}, /* mem address not aligned */
577 {0x09, SIGSEGV
}, /* data access exception */
578 {0x0a, SIGEMT
}, /* tag overflow */
579 {0x20, SIGBUS
}, /* r register access error */
580 {0x21, SIGBUS
}, /* instruction access error */
581 {0x24, SIGEMT
}, /* cp disabled */
582 {0x29, SIGBUS
}, /* data access error */
583 {0x2a, SIGFPE
}, /* divide by zero */
584 {0x2b, SIGBUS
}, /* data store error */
585 {0x80+1, SIGTRAP
}, /* ta 1 - normal breakpoint instruction */
586 {0xff, SIGTRAP
}, /* hardware breakpoint */
587 {0, 0} /* Must be last */
590 /* Set up exception handlers for tracing and breakpoints */
595 struct hard_trap_info
*ht
;
597 /* Only setup fp traps if the FP is disabled. */
599 for (ht
= hard_trap_info
;
600 ht
->tt
!= 0 && ht
->signo
!= 0;
602 if (ht
->tt
!= 4 || ! (read_psr () & 0x1000))
603 exceptionHandler(ht
->tt
, trap_low
);
609 ! Trap handler for memory errors. This just sets mem_err to be non-zero. It
610 ! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
611 ! 0 would ever contain code that could mem fault. This routine will skip
612 ! past the faulting instruction after setting mem_err.
618 sethi %hi(_mem_err), %l0
619 st %l1, [%l0 + %lo(_mem_err)]
625 set_mem_fault_trap(enable
)
628 extern void fltr_set_mem_err();
632 exceptionHandler(9, fltr_set_mem_err
);
634 exceptionHandler(9, trap_low
);
641 _dummy_hw_breakpoint:
651 extern void dummy_hw_breakpoint();
653 exceptionHandler (255, dummy_hw_breakpoint
);
657 exceptionHandler (255, trap_low
);
660 /* Convert the SPARC hardware trap type code to a unix signal number. */
666 struct hard_trap_info
*ht
;
668 for (ht
= hard_trap_info
; ht
->tt
&& ht
->signo
; ht
++)
672 return SIGHUP
; /* default for things we don't know about */
676 * While we find nice hex chars, build an int.
677 * Return number of chars processed.
681 hexToInt(char **ptr
, int *intValue
)
690 hexValue
= hex(**ptr
);
694 *intValue
= (*intValue
<< 4) | hexValue
;
704 * This function does all command procesing for interfacing to gdb. It
705 * 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 get_in_break_mode (); /* Enable DSU register writes */
743 registers
[DIA1
] = read_asi (1, 0xff00);
744 registers
[DIA2
] = read_asi (1, 0xff04);
745 registers
[DDA1
] = read_asi (1, 0xff08);
746 registers
[DDA2
] = read_asi (1, 0xff0c);
747 registers
[DDV1
] = read_asi (1, 0xff10);
748 registers
[DDV2
] = read_asi (1, 0xff14);
749 registers
[DCR
] = read_asi (1, 0xff18);
750 registers
[DSR
] = read_asi (1, 0xff1c);
752 if (registers
[PC
] == (unsigned long)breakinst
)
754 registers
[PC
] = registers
[NPC
];
757 sp
= (unsigned long *)registers
[SP
];
759 dsr
= (unsigned long)registers
[DSR
];
763 tt
= (registers
[TBR
] >> 4) & 0xff;
765 /* reply to host that an exception has occurred */
766 sigval
= computeSignal(tt
);
767 ptr
= remcomOutBuffer
;
770 *ptr
++ = hexchars
[sigval
>> 4];
771 *ptr
++ = hexchars
[sigval
& 0xf];
773 *ptr
++ = hexchars
[PC
>> 4];
774 *ptr
++ = hexchars
[PC
& 0xf];
776 ptr
= mem2hex((char *)®isters
[PC
], ptr
, 4, 0);
779 *ptr
++ = hexchars
[FP
>> 4];
780 *ptr
++ = hexchars
[FP
& 0xf];
782 ptr
= mem2hex(sp
+ 8 + 6, ptr
, 4, 0); /* FP */
785 *ptr
++ = hexchars
[SP
>> 4];
786 *ptr
++ = hexchars
[SP
& 0xf];
788 ptr
= mem2hex((char *)&sp
, ptr
, 4, 0);
791 *ptr
++ = hexchars
[NPC
>> 4];
792 *ptr
++ = hexchars
[NPC
& 0xf];
794 ptr
= mem2hex((char *)®isters
[NPC
], ptr
, 4, 0);
797 *ptr
++ = hexchars
[O7
>> 4];
798 *ptr
++ = hexchars
[O7
& 0xf];
800 ptr
= mem2hex((char *)®isters
[O7
], ptr
, 4, 0);
805 putpacket(remcomOutBuffer
);
809 remcomOutBuffer
[0] = 0;
811 getpacket(remcomInBuffer
);
812 switch (remcomInBuffer
[0])
815 remcomOutBuffer
[0] = 'S';
816 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
817 remcomOutBuffer
[2] = hexchars
[sigval
& 0xf];
818 remcomOutBuffer
[3] = 0;
822 /* toggle debug flag */
825 case 'g': /* return the value of the CPU registers */
826 memcpy (®isters
[L0
], sp
, 16 * 4); /* Copy L & I regs from stack */
827 mem2hex ((char *)registers
, remcomOutBuffer
, NUMREGBYTES
, 0);
830 case 'G': /* Set the value of all registers */
831 case 'P': /* Set the value of one register */
833 unsigned long *newsp
, psr
;
835 psr
= registers
[PSR
];
837 ptr
= &remcomInBuffer
[1];
839 if (remcomInBuffer
[0] == 'P')
843 if (hexToInt (&ptr
, ®no
)
845 if (regno
>= L0
&& regno
<= I7
)
846 hex2mem (ptr
, sp
+ regno
- L0
, 4, 0);
848 hex2mem (ptr
, (char *)®isters
[regno
], 4, 0);
851 strcpy (remcomOutBuffer
, "P01");
857 hex2mem (ptr
, (char *)registers
, NUMREGBYTES
, 0);
858 memcpy (sp
, ®isters
[L0
], 16 * 4); /* Copy L & I regs to stack */
861 /* See if the stack pointer has moved. If so, then copy the saved
862 locals and ins to the new location. This keeps the window
863 overflow and underflow routines happy. */
865 newsp
= (unsigned long *)registers
[SP
];
867 sp
= memcpy(newsp
, sp
, 16 * 4);
869 /* Don't allow CWP to be modified. */
871 if (psr
!= registers
[PSR
])
872 registers
[PSR
] = (psr
& 0x1f) | (registers
[PSR
] & ~0x1f);
874 strcpy(remcomOutBuffer
,"OK");
878 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
879 /* Try to read %x,%x. */
881 ptr
= &remcomInBuffer
[1];
883 if (hexToInt(&ptr
, &addr
)
885 && hexToInt(&ptr
, &length
))
887 if (mem2hex((char *)addr
, remcomOutBuffer
, length
, 1))
890 strcpy (remcomOutBuffer
, "E03");
893 strcpy(remcomOutBuffer
,"E01");
896 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
897 /* Try to read '%x,%x:'. */
899 ptr
= &remcomInBuffer
[1];
901 if (hexToInt(&ptr
, &addr
)
903 && hexToInt(&ptr
, &length
)
906 if (hex2mem(ptr
, (char *)addr
, length
, 1))
907 strcpy(remcomOutBuffer
, "OK");
909 strcpy(remcomOutBuffer
, "E03");
912 strcpy(remcomOutBuffer
, "E02");
915 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
916 /* try to read optional parameter, pc unchanged if no parm */
918 ptr
= &remcomInBuffer
[1];
919 if (hexToInt(&ptr
, &addr
))
921 registers
[PC
] = addr
;
922 registers
[NPC
] = addr
+ 4;
925 /* Need to flush the instruction cache here, as we may have deposited a
926 breakpoint, and the icache probably has no way of knowing that a data ref to
927 some location may have changed something that is in the instruction cache.
932 if (!(registers
[DSR
] & 0x1) /* DSU enabled? */
933 && !(registers
[DCR
] & 0x200)) /* Are we in break state? */
934 { /* Yes, set the DSU regs */
935 write_asi (1, 0xff00, registers
[DIA1
]);
936 write_asi (1, 0xff04, registers
[DIA2
]);
937 write_asi (1, 0xff08, registers
[DDA1
]);
938 write_asi (1, 0xff0c, registers
[DDA2
]);
939 write_asi (1, 0xff10, registers
[DDV1
]);
940 write_asi (1, 0xff14, registers
[DDV2
]);
941 write_asi (1, 0xff1c, registers
[DSR
]);
942 write_asi (1, 0xff18, registers
[DCR
] | 0x200); /* Clear break */
947 /* kill the program */
948 case 'k' : /* do nothing */
951 case 't': /* Test feature */
952 asm (" std %f30,[%sp]");
955 case 'r': /* Reset */
961 Disabled until we can unscrew
this properly
963 case 'b': /* bBB... Set baud rate to BB... */
966 extern void set_timer_3();
968 ptr
= &remcomInBuffer
[1];
969 if (!hexToInt(&ptr
, &baudrate
))
971 strcpy(remcomOutBuffer
,"B01");
975 /* Convert baud rate to uart clock divider */
988 strcpy(remcomOutBuffer
,"B02");
992 putpacket("OK"); /* Ack before changing speed */
993 set_timer_3(baudrate
); /* Set it */
999 /* reply to the request */
1000 putpacket(remcomOutBuffer
);
1004 /* This function will generate a breakpoint exception. It is used at the
1005 beginning of a program to sync up with a debugger and can be used
1006 otherwise as a quick means to stop program execution and "break" into
1015 asm(" .globl _breakinst