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