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