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