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