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