Add missed log entry for som.c.
[deliverable/binutils-gdb.git] / gdb / sparcl-stub.c
CommitLineData
b955f680
KH
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 * 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.
35 *
36 * This code has been extensively tested on the Fujitsu SPARClite demo board.
37 *
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.
44 *
45 *************
46 *
47 * The following gdb commands are supported:
48 *
49 * command function Return value
50 *
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
53 *
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
56 *
57 * c Resume at current address SNN ( signal NN)
58 * cAA..AA Continue at address AA..AA SNN
59 *
60 * s Step one instruction SNN
61 * sAA..AA Step one instruction from AA..AA SNN
62 *
63 * k kill
64 *
65 * ? What was the last sigval ? SNN (signal NN)
66 *
67 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
68 * baud rate
69 *
70 * All commands and responses are sent with a packet which includes a
71 * checksum. A packet consists of
72 *
73 * $<packet info>#<checksum>.
74 *
75 * where
76 * <packet info> :: <characters representing the command or response>
77 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
78 *
79 * When a packet is received, it is first acknowledged with either '+' or '-'.
80 * '+' indicates a successful transfer. '-' indicates a failed transfer.
81 *
82 * Example:
83 *
84 * Host: Reply:
85 * $m0,10#2a +$00010203040506070809101112131415#42
86 *
87 ****************************************************************************/
88
b955f680
KH
89#include <string.h>
90#include <signal.h>
91
92/************************************************************************
93 *
94 * external low-level support routines
95 */
96
97extern putDebugChar(); /* write a single character */
98extern getDebugChar(); /* read and return a single char */
99
100/************************************************************************/
101/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
102/* at least NUMREGBYTES*2 are needed for register packets */
103#define BUFMAX 2048
104
105static int initialized = 0; /* !0 means we've been initialized */
106
107extern void breakinst();
108static void hw_breakpoint();
109static void set_mem_fault_trap();
110static void get_in_break_mode();
111
112static const char hexchars[]="0123456789abcdef";
113
114#define NUMREGS 80
115
116/* Number of bytes of registers. */
117#define NUMREGBYTES (NUMREGS * 4)
118enum 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,
122
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 };
129
130/*************************** ASSEMBLY CODE MACROS *************************/
131/* */
132
133extern void trap_low();
134
135asm("
136 .reserve trapstack, 1000 * 4, \"bss\", 8
137
138 .data
139 .align 4
140
141in_trap_handler:
142 .word 0
143
144 .text
145 .align 4
146
147! This function is called when any SPARC trap (except window overflow or
148! underflow) occurs. It makes sure that the invalid register window is still
149! available before jumping into C code. It will also restore the world if you
150! return from handle_exception.
151
152 .globl _trap_low
153_trap_low:
154 mov %psr, %l0
155 mov %wim, %l3
156
157 srl %l3, %l0, %l4 ! wim >> cwp
158 cmp %l4, 1
159 bne window_fine ! Branch if not in the invalid window
160 nop
161
162! Handle window overflow
163
164 mov %g1, %l4 ! Save g1, we use it to hold the wim
165 srl %l3, 1, %g1 ! Rotate wim right
166 tst %g1
167 bg good_wim ! Branch if new wim is non-zero
168
169! At this point, we need to bring a 1 into the high order bit of the wim.
170! Since we don't want to make any assumptions about the number of register
171! windows, we figure it out dynamically so as to setup the wim correctly.
172
173 not %g1 ! Fill g1 with ones
174 mov %g1, %wim ! Fill the wim with ones
175 nop
176 nop
177 nop
178 mov %wim, %g1 ! Read back the wim
179 inc %g1 ! Now g1 has 1 just to left of wim
180 srl %g1, 1, %g1 ! Now put 1 at top of wim
181 mov %g0, %wim ! Clear wim so that subsequent save
182 nop ! won't trap
183 nop
184 nop
185
186good_wim:
187 save %g0, %g0, %g0 ! Slip into next window
188 mov %g1, %wim ! Install the new wim
189
190 std %l0, [%sp + 0 * 4] ! save L & I registers
191 std %l2, [%sp + 2 * 4]
192 std %l4, [%sp + 4 * 4]
193 std %l6, [%sp + 6 * 4]
194
195 std %i0, [%sp + 8 * 4]
196 std %i2, [%sp + 10 * 4]
197 std %i4, [%sp + 12 * 4]
198 std %i6, [%sp + 14 * 4]
199
200 restore ! Go back to trap window.
201 mov %l4, %g1 ! Restore %g1
202
203window_fine:
204 sethi %hi(in_trap_handler), %l4
205 ld [%lo(in_trap_handler) + %l4], %l5
206 tst %l5
207 bg recursive_trap
208 inc %l5
209
210 set trapstack+1000*4, %sp ! Switch to trap stack
211
212recursive_trap:
213 st %l5, [%lo(in_trap_handler) + %l4]
214 sub %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals
215 ! + hidden arg + arg spill
216 ! + doubleword alignment
217 ! + registers[72] local var
218
219 std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
220 std %g2, [%sp + (24 + 2) * 4]
221 std %g4, [%sp + (24 + 4) * 4]
222 std %g6, [%sp + (24 + 6) * 4]
223
224 std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
225 std %i2, [%sp + (24 + 10) * 4]
226 std %i4, [%sp + (24 + 12) * 4]
227 std %i6, [%sp + (24 + 14) * 4]
228 ! F0->F31 not implemented
229 mov %y, %l4
230 mov %tbr, %l5
231 st %l4, [%sp + (24 + 64) * 4] ! Y
232 st %l0, [%sp + (24 + 65) * 4] ! PSR
233 st %l3, [%sp + (24 + 66) * 4] ! WIM
234 st %l5, [%sp + (24 + 67) * 4] ! TBR
235 st %l1, [%sp + (24 + 68) * 4] ! PC
236 st %l2, [%sp + (24 + 69) * 4] ! NPC
237 ! CPSR and FPSR not impl
238 or %l0, 0xf20, %l4
239 mov %l4, %psr ! Turn on traps, disable interrupts
240 nop
241 nop
242 nop
243 call _get_in_break_mode
244 nop
245 nop
246 nop
247
248 sethi %hi(0xff00), %l5
249 or %l5, %lo(0xff00), %l5
250
251 lda [%l5]0x1, %l4
252 st %l4, [%sp + (24 + 72) * 4] ! DIA1, debug instr addr 1
253 add %l5, 4, %l5
254 lda [%l5]0x1, %l4
255 st %l4, [%sp + (24 + 73) * 4] ! DIA2, debug instr addr 2
256 add %l5, 4, %l5
257 lda [%l5]0x1, %l4
258 st %l4, [%sp + (24 + 74) * 4] ! DDA1, debug data addr 1
259 add %l5, 4, %l5
260 lda [%l5]0x1, %l4
261 st %l4, [%sp + (24 + 75) * 4] ! DDA2, debug data addr 2
262 add %l5, 4, %l5
263 lda [%l5]0x1, %l4
264 st %l4, [%sp + (24 + 76) * 4] ! DDV1, debug data val 1
265 add %l5, 4, %l5
266 lda [%l5]0x1, %l4
267 st %l4, [%sp + (24 + 77) * 4] ! DDV2, debug data val 2
268 add %l5, 4, %l5
269 lda [%l5]0x1, %l4
270 st %l4, [%sp + (24 + 78) * 4] ! DCR, debug control reg
271 add %l5, 4, %l5
272 lda [%l5]0x1, %l4
273 st %l4, [%sp + (24 + 79) * 4] ! DSR, debug status reg
274 nop
275 nop
276 or %l0, 0xf20, %l4
277 mov %l4, %psr ! Turn on traps, disable interrupts
278 nop
279 nop
280 nop
281 call _handle_exception
282 add %sp, 24 * 4, %o0 ! Pass address of registers
283
284! Reload all of the registers that aren't on the stack
285
286 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
287 ldd [%sp + (24 + 2) * 4], %g2
288 ldd [%sp + (24 + 4) * 4], %g4
289 ldd [%sp + (24 + 6) * 4], %g6
290
291 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
292 ldd [%sp + (24 + 10) * 4], %i2
293 ldd [%sp + (24 + 12) * 4], %i4
294 ldd [%sp + (24 + 14) * 4], %i6
295
296 sethi %hi(0xff00), %l2
297 or %l2, %lo(0xff00), %l2
298 ldd [%sp + (24 + 72) * 4], %l4 ! DIA1, debug instr addr 1
299 stda %l4, [%l2]0x1
300 nop
301 nop
302 nop
303 nop
304 ldd [%sp + (24 + 74) * 4], %l4 ! DDA1, debug data addr 1
305 add %l2, 8, %l2
306 stda %l4, [%l2]0x1
307 nop
308 nop
309 nop
310 nop
311 ldd [%sp + (24 + 76) * 4], %l4 ! DDV1, debug data value 1
312 add %l2, 8, %l2
313 stda %l4, [%l2]0x1
314 nop
315 nop
316 nop
317 nop
318 ld [%sp + (24 + 78) * 4], %l4 ! DCR, debug control reg
319 ld [%sp + (24 + 79) * 4], %l5 ! DSR, debug control reg
320 add %l2, 8, %l2
321 or %l4, 0x200, %l4
322 sta %l4, [%l2]0x1
323 add %l2, 4, %l2
324 sta %l5, [%l2]0x1
325 nop
326 nop
327 nop
328 nop
329
330 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
331 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
332
333 restore ! Ensure that previous window is valid
334 save %g0, %g0, %g0 ! by causing a window_underflow trap
335
336 mov %l0, %y
337 mov %l1, %psr ! Make sure that traps are disabled
338 ! for rett
339 sethi %hi(in_trap_handler), %l4
340 ld [%lo(in_trap_handler) + %l4], %l5
341 dec %l5
342 st %l5, [%lo(in_trap_handler) + %l4]
343
344 jmpl %l2, %g0 ! Restore old PC
345 rett %l3 ! Restore old nPC
346");
347
348/* Convert ch from a hex digit to an int */
349
350static int
351hex(ch)
352 unsigned char ch;
353{
354 if (ch >= 'a' && ch <= 'f')
355 return ch-'a'+10;
356 if (ch >= '0' && ch <= '9')
357 return ch-'0';
358 if (ch >= 'A' && ch <= 'F')
359 return ch-'A'+10;
360 return -1;
361}
362
363/* scan for the sequence $<data>#<checksum> */
364
365static void
366getpacket(buffer)
367 char *buffer;
368{
369 unsigned char checksum;
370 unsigned char xmitcsum;
371 int i;
372 int count;
373 unsigned char ch;
374
375 do
376 {
377 /* wait around for the start character, ignore all other characters */
2d4838fe 378 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
b955f680
KH
379
380 checksum = 0;
381 xmitcsum = -1;
382
383 count = 0;
384
385 /* now, read until a # or end of buffer is found */
386 while (count < BUFMAX)
387 {
2d4838fe 388 ch = getDebugChar() & 0x7f;
b955f680
KH
389 if (ch == '#')
390 break;
391 checksum = checksum + ch;
392 buffer[count] = ch;
393 count = count + 1;
394 }
395
396 if (count >= BUFMAX)
397 continue;
398
399 buffer[count] = 0;
400
401 if (ch == '#')
402 {
2d4838fe
SS
403 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
404 xmitcsum |= hex(getDebugChar() & 0x7f);
b955f680
KH
405#if 0
406 /* Humans shouldn't have to figure out checksums to type to it. */
407 putDebugChar ('+');
408 return;
409#endif
410 if (checksum != xmitcsum)
411 putDebugChar('-'); /* failed checksum */
412 else
413 {
414 putDebugChar('+'); /* successful transfer */
415 /* if a sequence char is present, reply the sequence ID */
416 if (buffer[2] == ':')
417 {
418 putDebugChar(buffer[0]);
419 putDebugChar(buffer[1]);
420 /* remove sequence chars from buffer */
421 count = strlen(buffer);
422 for (i=3; i <= count; i++)
423 buffer[i-3] = buffer[i];
424 }
425 }
426 }
427 }
428 while (checksum != xmitcsum);
429}
430
431/* send the packet in buffer. */
432
433static void
434putpacket(buffer)
435 unsigned char *buffer;
436{
437 unsigned char checksum;
438 int count;
439 unsigned char ch;
440
441 /* $<packet info>#<checksum>. */
442 do
443 {
444 putDebugChar('$');
445 checksum = 0;
446 count = 0;
447
448 while (ch = buffer[count])
449 {
450 if (! putDebugChar(ch))
451 return;
452 checksum += ch;
453 count += 1;
454 }
455
456 putDebugChar('#');
457 putDebugChar(hexchars[checksum >> 4]);
458 putDebugChar(hexchars[checksum & 0xf]);
459
460 }
2d4838fe 461 while ((getDebugChar() & 0x7f) != '+');
b955f680
KH
462}
463
464static char remcomInBuffer[BUFMAX];
465static char remcomOutBuffer[BUFMAX];
466
467/* Indicate to caller of mem2hex or hex2mem that there has been an
468 error. */
469static volatile int mem_err = 0;
470
471/* Convert the memory pointed to by mem into hex, placing result in buf.
472 * Return a pointer to the last char put in buf (null), in case of mem fault,
473 * return 0.
474 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
475 * a 0, else treat a fault like any other fault in the stub.
476 */
477
478static unsigned char *
479mem2hex(mem, buf, count, may_fault)
480 unsigned char *mem;
481 unsigned char *buf;
482 int count;
483 int may_fault;
484{
485 unsigned char ch;
486
487 set_mem_fault_trap(may_fault);
488
489 while (count-- > 0)
490 {
491 ch = *mem++;
492 if (mem_err)
493 return 0;
494 *buf++ = hexchars[ch >> 4];
495 *buf++ = hexchars[ch & 0xf];
496 }
497
498 *buf = 0;
499
500 set_mem_fault_trap(0);
501
502 return buf;
503}
504
505/* convert the hex array pointed to by buf into binary to be placed in mem
506 * return a pointer to the character AFTER the last byte written */
507
508static char *
509hex2mem(buf, mem, count, may_fault)
510 unsigned char *buf;
511 unsigned char *mem;
512 int count;
513 int may_fault;
514{
515 int i;
516 unsigned char ch;
517
518 set_mem_fault_trap(may_fault);
519
520 for (i=0; i<count; i++)
521 {
522 ch = hex(*buf++) << 4;
523 ch |= hex(*buf++);
524 *mem++ = ch;
525 if (mem_err)
526 return 0;
527 }
528
529 set_mem_fault_trap(0);
530
531 return mem;
532}
533
534/* This table contains the mapping between SPARC hardware trap types, and
535 signals, which are primarily what GDB understands. It also indicates
536 which hardware traps we need to commandeer when initializing the stub. */
537
538static struct hard_trap_info
539{
540 unsigned char tt; /* Trap type code for SPARClite */
541 unsigned char signo; /* Signal that we map this trap into */
542} hard_trap_info[] = {
543 {1, SIGSEGV}, /* instruction access error */
544 {2, SIGILL}, /* privileged instruction */
545 {3, SIGILL}, /* illegal instruction */
546 {4, SIGEMT}, /* fp disabled */
547 {36, SIGEMT}, /* cp disabled */
548 {7, SIGBUS}, /* mem address not aligned */
549 {9, SIGSEGV}, /* data access exception */
550 {10, SIGEMT}, /* tag overflow */
551 {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
552 {255, SIGTRAP}, /* hardware breakpoint */
553 {0, 0} /* Must be last */
554};
555
556/* Set up exception handlers for tracing and breakpoints */
557
558void
559set_debug_traps()
560{
561 struct hard_trap_info *ht;
562
563 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
564 exceptionHandler(ht->tt, trap_low);
565
566 /* In case GDB is started before us, ack any packets (presumably
567 "$?#xx") sitting there. */
568
569 putDebugChar ('+');
570
571 initialized = 1;
572}
573
574asm ("
575! Trap handler for memory errors. This just sets mem_err to be non-zero. It
576! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
577! 0 would ever contain code that could mem fault. This routine will skip
578! past the faulting instruction after setting mem_err.
579
580 .text
581 .align 4
582
583_fltr_set_mem_err:
584 sethi %hi(_mem_err), %l0
585 st %l1, [%l0 + %lo(_mem_err)]
586 jmpl %l2, %g0
587 rett %l2+4
588");
589
590static void
591set_mem_fault_trap(enable)
592 int enable;
593{
594 extern void fltr_set_mem_err();
595 mem_err = 0;
596
597 if (enable)
598 exceptionHandler(9, fltr_set_mem_err);
599 else
600 exceptionHandler(9, trap_low);
601}
602
603asm ("
604 .text
605 .align 4
606
607_dummy_hw_breakpoint:
608 jmpl %l2, %g0
609 rett %l2+4
610 nop
611 nop
612");
613
614static void
615set_hw_breakpoint_trap(enable)
616 int enable;
617{
618 extern void dummy_hw_breakpoint();
619
620 if (enable)
621 exceptionHandler(255, dummy_hw_breakpoint);
622 else
623 exceptionHandler(255, trap_low);
624}
625
626static void
627get_in_break_mode()
628{
629 set_hw_breakpoint_trap(1);
630
631 asm("
632 sethi %hi(0xff10), %l4
633 or %l4, %lo(0xff10), %l4
634 sta %g0, [%l4]0x1
635 nop
636 nop
637 nop
638 ");
639
640 set_hw_breakpoint_trap(0);
641}
642
643/* Convert the SPARC hardware trap type code to a unix signal number. */
644
645static int
646computeSignal(tt)
647 int tt;
648{
649 struct hard_trap_info *ht;
650
651 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
652 if (ht->tt == tt)
653 return ht->signo;
654
655 return SIGHUP; /* default for things we don't know about */
656}
657
658/*
659 * While we find nice hex chars, build an int.
660 * Return number of chars processed.
661 */
662
663static int
664hexToInt(char **ptr, int *intValue)
665{
666 int numChars = 0;
667 int hexValue;
668
669 *intValue = 0;
670
671 while (**ptr)
672 {
673 hexValue = hex(**ptr);
674 if (hexValue < 0)
675 break;
676
677 *intValue = (*intValue << 4) | hexValue;
678 numChars ++;
679
680 (*ptr)++;
681 }
682
683 return (numChars);
684}
685
686/*
687 * This function does all command procesing for interfacing to gdb. It
688 * returns 1 if you should skip the instruction at the trap address, 0
689 * otherwise.
690 */
691
692
693static void
694handle_exception (registers)
695 unsigned long *registers;
696{
697 int tt; /* Trap type */
698 int sigval;
699 int addr;
700 int length;
701 char *ptr;
702 unsigned long *sp;
703 unsigned long dsr;
704
705/* First, we must force all of the windows to be spilled out */
706
707 asm(" save %sp, -64, %sp
708 save %sp, -64, %sp
709 save %sp, -64, %sp
710 save %sp, -64, %sp
711 save %sp, -64, %sp
712 save %sp, -64, %sp
713 save %sp, -64, %sp
714 save %sp, -64, %sp
715 restore
716 restore
717 restore
718 restore
719 restore
720 restore
721 restore
722 restore
723");
724
725 if (registers[PC] == (unsigned long)breakinst)
726 {
727 registers[PC] = registers[NPC];
728 registers[NPC] += 4;
729 }
730 sp = (unsigned long *)registers[SP];
731
732 dsr = (unsigned long)registers[DSR];
733 if (dsr & 0x3c)
734 {
735 tt = 255;
736 }
737 else
738 {
739 tt = (registers[TBR] >> 4) & 0xff;
740 }
741
742 /* reply to host that an exception has occurred */
743 sigval = computeSignal(tt);
744 ptr = remcomOutBuffer;
745
746 *ptr++ = 'T';
747 *ptr++ = hexchars[sigval >> 4];
748 *ptr++ = hexchars[sigval & 0xf];
749
750 *ptr++ = hexchars[PC >> 4];
751 *ptr++ = hexchars[PC & 0xf];
752 *ptr++ = ':';
753 ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
754 *ptr++ = ';';
755
756 *ptr++ = hexchars[FP >> 4];
757 *ptr++ = hexchars[FP & 0xf];
758 *ptr++ = ':';
759 ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
760 *ptr++ = ';';
761
762 *ptr++ = hexchars[SP >> 4];
763 *ptr++ = hexchars[SP & 0xf];
764 *ptr++ = ':';
765 ptr = mem2hex((char *)&sp, ptr, 4, 0);
766 *ptr++ = ';';
767
768 *ptr++ = hexchars[NPC >> 4];
769 *ptr++ = hexchars[NPC & 0xf];
770 *ptr++ = ':';
771 ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
772 *ptr++ = ';';
773
774 *ptr++ = hexchars[O7 >> 4];
775 *ptr++ = hexchars[O7 & 0xf];
776 *ptr++ = ':';
777 ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
778 *ptr++ = ';';
779
780 *ptr++ = 0;
781
782 putpacket(remcomOutBuffer);
783
784 while (1)
785 {
786 remcomOutBuffer[0] = 0;
787
788 getpacket(remcomInBuffer);
789 switch (remcomInBuffer[0])
790 {
791 case '?':
792 remcomOutBuffer[0] = 'S';
793 remcomOutBuffer[1] = hexchars[sigval >> 4];
794 remcomOutBuffer[2] = hexchars[sigval & 0xf];
795 remcomOutBuffer[3] = 0;
796 break;
797
798 case 'd':
799 /* toggle debug flag */
800 break;
801
802 case 'g': /* return the value of the CPU registers */
803 {
804 ptr = remcomOutBuffer;
805 ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
806 ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
807 memset(ptr, '0', 32 * 8); /* Floating point */
808 ptr = mem2hex((char *)&registers[Y],
809 ptr + 32 * 4 * 2,
810 8 * 4,
811 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
812 mem2hex((char *)&registers[DIA1], ptr,
813 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */
814 }
815 break;
816
817 case 'G': /* set the value of the CPU registers - return OK */
818 {
819 unsigned long *newsp, psr;
820
821 psr = registers[PSR];
822
823 ptr = &remcomInBuffer[1];
824 hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
825 hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
826 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
827 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
828 hex2mem(ptr + 72 * 4 * 2, (char *)&registers[DIA1],
829 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */
830
831 /* See if the stack pointer has moved. If so, then copy the saved
832 locals and ins to the new location. This keeps the window
833 overflow and underflow routines happy. */
834
835 newsp = (unsigned long *)registers[SP];
836 if (sp != newsp)
837 sp = memcpy(newsp, sp, 16 * 4);
838
839 /* Don't allow CWP to be modified. */
840
841 if (psr != registers[PSR])
842 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
843
844 strcpy(remcomOutBuffer,"OK");
845 }
846 break;
847
848 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
849 /* Try to read %x,%x. */
850
851 ptr = &remcomInBuffer[1];
852
853 if (hexToInt(&ptr, &addr)
854 && *ptr++ == ','
855 && hexToInt(&ptr, &length))
856 {
857 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
858 break;
859
860 strcpy (remcomOutBuffer, "E03");
861 }
862 else
863 strcpy(remcomOutBuffer,"E01");
864 break;
865
866 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
867 /* Try to read '%x,%x:'. */
868
869 ptr = &remcomInBuffer[1];
870
871 if (hexToInt(&ptr, &addr)
872 && *ptr++ == ','
873 && hexToInt(&ptr, &length)
874 && *ptr++ == ':')
875 {
876 if (hex2mem(ptr, (char *)addr, length, 1))
877 strcpy(remcomOutBuffer, "OK");
878 else
879 strcpy(remcomOutBuffer, "E03");
880 }
881 else
882 strcpy(remcomOutBuffer, "E02");
883 break;
884
885 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
886 /* try to read optional parameter, pc unchanged if no parm */
887
888 ptr = &remcomInBuffer[1];
889 if (hexToInt(&ptr, &addr))
890 {
891 registers[PC] = addr;
892 registers[NPC] = addr + 4;
893 }
894
895/* Need to flush the instruction cache here, as we may have deposited a
896 breakpoint, and the icache probably has no way of knowing that a data ref to
897 some location may have changed something that is in the instruction cache.
898 */
899
900 flush_i_cache();
901 return;
902
903 /* kill the program */
904 case 'k' : /* do nothing */
905 break;
906#if 0
907 case 't': /* Test feature */
908 asm (" std %f30,[%sp]");
909 break;
910#endif
911 case 'r': /* Reset */
912 asm ("call 0
913 nop ");
914 break;
915
916#if 0
917Disabled until we can unscrew this properly
918
919 case 'b': /* bBB... Set baud rate to BB... */
920 {
921 int baudrate;
922 extern void set_timer_3();
923
924 ptr = &remcomInBuffer[1];
925 if (!hexToInt(&ptr, &baudrate))
926 {
927 strcpy(remcomOutBuffer,"B01");
928 break;
929 }
930
931 /* Convert baud rate to uart clock divider */
932 switch (baudrate)
933 {
934 case 38400:
935 baudrate = 16;
936 break;
937 case 19200:
938 baudrate = 33;
939 break;
940 case 9600:
941 baudrate = 65;
942 break;
943 default:
944 strcpy(remcomOutBuffer,"B02");
945 goto x1;
946 }
947
948 putpacket("OK"); /* Ack before changing speed */
949 set_timer_3(baudrate); /* Set it */
950 }
951x1: break;
952#endif
953 } /* switch */
954
955 /* reply to the request */
956 putpacket(remcomOutBuffer);
957 }
958}
959
960/* This function will generate a breakpoint exception. It is used at the
961 beginning of a program to sync up with a debugger and can be used
962 otherwise as a quick means to stop program execution and "break" into
963 the debugger. */
964
965void
966breakpoint()
967{
968 if (!initialized)
969 return;
970
971 asm(" .globl _breakinst
972
973 _breakinst: ta 1
974 ");
975}
976
977static void
978hw_breakpoint()
979{
980 asm("
981 ta 127
982 ");
983}
This page took 0.088792 seconds and 4 git commands to generate.