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