Update .sanitize files
[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 * 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 *
63 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
64 * baud rate
65 *
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
85 #include <string.h>
86 #include <signal.h>
87 #include <memory.h>
88
89 /************************************************************************
90 *
91 * external low-level support routines
92 */
93
94 extern putDebugChar(); /* write a single character */
95 extern 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
102 static int initialized; /* boolean flag. != 0 means we've been initialized */
103
104 static void set_mem_fault_trap();
105
106 static const char hexchars[]="0123456789abcdef";
107
108 #define NUMREGS 72
109
110 /* Number of bytes of registers. */
111 #define NUMREGBYTES (NUMREGS * 4)
112 enum 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
123 /*************************** ASSEMBLY CODE MACROS *************************/
124 /* */
125
126 #define BREAKPOINT() asm(" ta 1");
127
128 extern unsigned long rdtbr();
129
130 asm("
131 .text
132 .align 4
133
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
146 trap_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
153 nop
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
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.
176 mov %l4, %g1 ! Restore %g1
177
178 window_fine:
179 sub %fp, (16+1+6+1+72)*4, %sp ! Make room for input & locals
180 ! + hidden arg + arg spill
181 ! + doubleword alignment
182 ! + registers[72] local var
183
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]
188
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]
193 ! F0->F31 not implemented
194 mov %y, %l4
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
202
203 ! CPSR and FPSR not impl
204
205 or %l0, 0xf20, %l4
206 mov %l4, %psr ! Turn on traps, disable interrupts
207
208 call _handle_exception
209 add %fp, -72 * 4, %o0 ! Pass address of registers
210
211 restore ! Ensure that previous window is valid
212 save %g0, %g0, %g0 ! by causing a window_underflow trap
213
214 ! Reload all of the registers that aren't on the stack
215
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
220
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
225
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
230 ! for rett
231 jmpl %l2, %g0 ! Restore old PC
232 rett %l3 ! Restore old nPC
233 ");
234
235 /* Convert ch from a hex digit to an int */
236
237 static int
238 hex(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
252 static void
253 getpacket(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());
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
320 static void
321 putpacket(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
351 static char remcomInBuffer[BUFMAX];
352 static char remcomOutBuffer[BUFMAX];
353
354 /* Indicate to caller of mem2hex or hex2mem that there has been an
355 error. */
356 static volatile int mem_err = 0;
357
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
365 static unsigned char *
366 mem2hex(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 {
378 ch = *mem++;
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
395 static char *
396 hex2mem(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++);
411 *mem++ = ch;
412 if (mem_err)
413 return 0;
414 }
415
416 set_mem_fault_trap(0);
417
418 return mem;
419 }
420
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
425 static 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
444 struct trap_entry
445 {
446 unsigned long ti[4];
447 };
448
449 extern struct trap_entry fltr_proto;
450 extern struct trap_entry fltr_set_mem_err;
451 asm ("
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
477 void
478 set_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
496 static void
497 set_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. */
513
514 static int
515 computeSignal(tt)
516 int tt;
517 {
518 struct hard_trap_info *ht;
519
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 */
525 }
526
527 /*
528 * While we find nice hex chars, build an int.
529 * Return number of chars processed.
530 */
531
532 static int
533 hexToInt(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);
543 if (hexValue < 0)
544 break;
545
546 *intValue = (*intValue << 4) | hexValue;
547 numChars ++;
548
549 (*ptr)++;
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
561 static void
562 handle_exception (registers)
563 unsigned long *registers;
564 {
565 int tt; /* Trap type */
566 int sigval;
567 int addr;
568 int length;
569 char *ptr;
570 unsigned long *sp;
571
572 /* First, we must force all of the windows to be spilled out */
573
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
582 restore
583 restore
584 restore
585 restore
586 restore
587 restore
588 restore
589 restore
590 ");
591
592 sp = (unsigned long *)registers[SP];
593
594 tt = (registers[TBR] >> 4) & 0xff;
595
596 /* reply to host that an exception has occurred */
597 sigval = computeSignal(tt);
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;
635
636 putpacket(remcomOutBuffer);
637
638 while (1)
639 {
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':
653 /* toggle debug flag */
654 break;
655
656 case 'g': /* return the value of the CPU registers */
657 {
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 */
663 mem2hex((char *)&registers[Y],
664 ptr + 32 * 4 * 2,
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 {
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],
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 */
683 /* Try to read %x,%x. */
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");
695 }
696 else
697 strcpy(remcomOutBuffer,"E01");
698 break;
699
700 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
701 /* Try to read '%x,%x:'. */
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
713 strcpy(remcomOutBuffer, "E03");
714 }
715 else
716 strcpy(remcomOutBuffer, "E02");
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
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();
736 return;
737
738 /* kill the program */
739 case 'k' : /* do nothing */
740 break;
741 #if 0
742 Disabled until we can unscrew this properly
743
744 case 'b': /* bBB... Set baud rate to BB... */
745 {
746 int baudrate;
747 extern void set_timer_3();
748
749 ptr = &remcomInBuffer[1];
750 if (!hexToInt(&ptr, &baudrate))
751 {
752 strcpy(remcomOutBuffer,"B01");
753 break;
754 }
755
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 }
772
773 putpacket("OK"); /* Ack before changing speed */
774 set_timer_3(baudrate); /* Set it */
775 }
776 x1: break;
777 #endif
778 } /* switch */
779
780 /* reply to the request */
781 putpacket(remcomOutBuffer);
782 }
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
790 void
791 breakpoint()
792 {
793 if (initialized)
794 BREAKPOINT();
795 }
This page took 0.044605 seconds and 4 git commands to generate.