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