* parse.c (write_dollar_variable): New function.
[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
9cc2cd4f 162 nop
39a13178 163
75a006d9
SG
164! At this point, we need to bring a 1 into the high order bit of the wim.
165! Since we don't want to make any assumptions about the number of register
166! windows, we figure it out dynamically so as to setup the wim correctly.
167
168 not %g1 ! Fill g1 with ones
169 mov %g1, %wim ! Fill the wim with ones
170 nop
171 nop
172 nop
173 mov %wim, %g1 ! Read back the wim
174 inc %g1 ! Now g1 has 1 just to left of wim
175 srl %g1, 1, %g1 ! Now put 1 at top of wim
176 mov %g0, %wim ! Clear wim so that subsequent save
177 nop ! won't trap
178 nop
179 nop
180
181good_wim:
39a13178
SG
182 save %g0, %g0, %g0 ! Slip into next window
183 mov %g1, %wim ! Install the new wim
184
185 std %l0, [%sp + 0 * 4] ! save L & I registers
4ecee2f9
SG
186 std %l2, [%sp + 2 * 4]
187 std %l4, [%sp + 4 * 4]
188 std %l6, [%sp + 6 * 4]
189
190 std %i0, [%sp + 8 * 4]
191 std %i2, [%sp + 10 * 4]
192 std %i4, [%sp + 12 * 4]
193 std %i6, [%sp + 14 * 4]
194
195 restore ! Go back to trap window.
39a13178 196 mov %l4, %g1 ! Restore %g1
4ecee2f9 197
39a13178 198window_fine:
bfc55a5d
SG
199 sethi %hi(in_trap_handler), %l4
200 ld [%lo(in_trap_handler) + %l4], %l5
201 tst %l5
202 bg recursive_trap
203 inc %l5
204
205 set trapstack+1000*4, %sp ! Switch to trap stack
206
207recursive_trap:
208 st %l5, [%lo(in_trap_handler) + %l4]
209 sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
4ecee2f9
SG
210 ! + hidden arg + arg spill
211 ! + doubleword alignment
39a13178 212 ! + registers[72] local var
4ecee2f9 213
bfc55a5d
SG
214 std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
215 std %g2, [%sp + (24 + 2) * 4]
216 std %g4, [%sp + (24 + 4) * 4]
217 std %g6, [%sp + (24 + 6) * 4]
4ecee2f9 218
bfc55a5d
SG
219 std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
220 std %i2, [%sp + (24 + 10) * 4]
221 std %i4, [%sp + (24 + 12) * 4]
222 std %i6, [%sp + (24 + 14) * 4]
4ecee2f9
SG
223 ! F0->F31 not implemented
224 mov %y, %l4
39a13178 225 mov %tbr, %l5
bfc55a5d
SG
226 st %l4, [%sp + (24 + 64) * 4] ! Y
227 st %l0, [%sp + (24 + 65) * 4] ! PSR
228 st %l3, [%sp + (24 + 66) * 4] ! WIM
229 st %l5, [%sp + (24 + 67) * 4] ! TBR
230 st %l1, [%sp + (24 + 68) * 4] ! PC
231 st %l2, [%sp + (24 + 69) * 4] ! NPC
4ecee2f9
SG
232
233 ! CPSR and FPSR not impl
234
39a13178
SG
235 or %l0, 0xf20, %l4
236 mov %l4, %psr ! Turn on traps, disable interrupts
4ecee2f9
SG
237
238 call _handle_exception
bfc55a5d 239 add %sp, 24 * 4, %o0 ! Pass address of registers
4ecee2f9 240
39a13178 241! Reload all of the registers that aren't on the stack
4ecee2f9 242
bfc55a5d
SG
243 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
244 ldd [%sp + (24 + 2) * 4], %g2
245 ldd [%sp + (24 + 4) * 4], %g4
246 ldd [%sp + (24 + 6) * 4], %g6
4ecee2f9 247
bfc55a5d
SG
248 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
249 ldd [%sp + (24 + 10) * 4], %i2
250 ldd [%sp + (24 + 12) * 4], %i4
251 ldd [%sp + (24 + 14) * 4], %i6
4ecee2f9 252
bfc55a5d
SG
253 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
254 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
f2e21136
SG
255
256 restore ! Ensure that previous window is valid
257 save %g0, %g0, %g0 ! by causing a window_underflow trap
258
39a13178
SG
259 mov %l0, %y
260 mov %l1, %psr ! Make sure that traps are disabled
4ecee2f9 261 ! for rett
bfc55a5d
SG
262
263 sethi %hi(in_trap_handler), %l4
264 ld [%lo(in_trap_handler) + %l4], %l5
265 dec %l5
266 st %l5, [%lo(in_trap_handler) + %l4]
267
39a13178
SG
268 jmpl %l2, %g0 ! Restore old PC
269 rett %l3 ! Restore old nPC
4ecee2f9
SG
270");
271
272/* Convert ch from a hex digit to an int */
273
274static int
275hex(ch)
276 unsigned char ch;
277{
278 if (ch >= 'a' && ch <= 'f')
279 return ch-'a'+10;
280 if (ch >= '0' && ch <= '9')
281 return ch-'0';
282 if (ch >= 'A' && ch <= 'F')
283 return ch-'A'+10;
284 return -1;
285}
286
287/* scan for the sequence $<data>#<checksum> */
288
289static void
290getpacket(buffer)
291 char *buffer;
292{
293 unsigned char checksum;
294 unsigned char xmitcsum;
295 int i;
296 int count;
297 unsigned char ch;
298
299 do
300 {
301 /* wait around for the start character, ignore all other characters */
2d4838fe 302 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
4ecee2f9
SG
303
304 checksum = 0;
305 xmitcsum = -1;
306
307 count = 0;
308
309 /* now, read until a # or end of buffer is found */
310 while (count < BUFMAX)
311 {
2d4838fe 312 ch = getDebugChar() & 0x7f;
4ecee2f9
SG
313 if (ch == '#')
314 break;
315 checksum = checksum + ch;
316 buffer[count] = ch;
317 count = count + 1;
318 }
319
320 if (count >= BUFMAX)
321 continue;
322
323 buffer[count] = 0;
324
325 if (ch == '#')
326 {
2d4838fe
SS
327 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
328 xmitcsum |= hex(getDebugChar() & 0x7f);
bfc55a5d
SG
329#if 0
330 /* Humans shouldn't have to figure out checksums to type to it. */
331 putDebugChar ('+');
332 return;
333#endif
4ecee2f9
SG
334 if (checksum != xmitcsum)
335 putDebugChar('-'); /* failed checksum */
336 else
337 {
338 putDebugChar('+'); /* successful transfer */
339 /* if a sequence char is present, reply the sequence ID */
340 if (buffer[2] == ':')
341 {
342 putDebugChar(buffer[0]);
343 putDebugChar(buffer[1]);
344 /* remove sequence chars from buffer */
345 count = strlen(buffer);
346 for (i=3; i <= count; i++)
347 buffer[i-3] = buffer[i];
348 }
349 }
350 }
351 }
352 while (checksum != xmitcsum);
353}
354
355/* send the packet in buffer. */
356
357static void
358putpacket(buffer)
359 unsigned char *buffer;
360{
361 unsigned char checksum;
362 int count;
363 unsigned char ch;
364
365 /* $<packet info>#<checksum>. */
366 do
367 {
368 putDebugChar('$');
369 checksum = 0;
370 count = 0;
371
372 while (ch = buffer[count])
373 {
374 if (! putDebugChar(ch))
375 return;
376 checksum += ch;
377 count += 1;
378 }
379
380 putDebugChar('#');
381 putDebugChar(hexchars[checksum >> 4]);
382 putDebugChar(hexchars[checksum & 0xf]);
383
384 }
2d4838fe 385 while ((getDebugChar() & 0x7f) != '+');
4ecee2f9
SG
386}
387
39a13178
SG
388static char remcomInBuffer[BUFMAX];
389static char remcomOutBuffer[BUFMAX];
4ecee2f9
SG
390
391/* Indicate to caller of mem2hex or hex2mem that there has been an
392 error. */
4ecee2f9
SG
393static volatile int mem_err = 0;
394
4ecee2f9
SG
395/* Convert the memory pointed to by mem into hex, placing result in buf.
396 * Return a pointer to the last char put in buf (null), in case of mem fault,
397 * return 0.
398 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
399 * a 0, else treat a fault like any other fault in the stub.
400 */
401
402static unsigned char *
403mem2hex(mem, buf, count, may_fault)
404 unsigned char *mem;
405 unsigned char *buf;
406 int count;
407 int may_fault;
408{
409 unsigned char ch;
410
411 set_mem_fault_trap(may_fault);
412
413 while (count-- > 0)
414 {
39a13178 415 ch = *mem++;
4ecee2f9
SG
416 if (mem_err)
417 return 0;
418 *buf++ = hexchars[ch >> 4];
419 *buf++ = hexchars[ch & 0xf];
420 }
421
422 *buf = 0;
423
424 set_mem_fault_trap(0);
425
426 return buf;
427}
428
429/* convert the hex array pointed to by buf into binary to be placed in mem
430 * return a pointer to the character AFTER the last byte written */
431
432static char *
433hex2mem(buf, mem, count, may_fault)
434 unsigned char *buf;
435 unsigned char *mem;
436 int count;
437 int may_fault;
438{
439 int i;
440 unsigned char ch;
441
442 set_mem_fault_trap(may_fault);
443
444 for (i=0; i<count; i++)
445 {
446 ch = hex(*buf++) << 4;
447 ch |= hex(*buf++);
39a13178 448 *mem++ = ch;
4ecee2f9
SG
449 if (mem_err)
450 return 0;
451 }
452
453 set_mem_fault_trap(0);
454
455 return mem;
456}
457
39a13178
SG
458/* This table contains the mapping between SPARC hardware trap types, and
459 signals, which are primarily what GDB understands. It also indicates
460 which hardware traps we need to commandeer when initializing the stub. */
461
462static struct hard_trap_info
463{
464 unsigned char tt; /* Trap type code for SPARClite */
465 unsigned char signo; /* Signal that we map this trap into */
466} hard_trap_info[] = {
467 {1, SIGSEGV}, /* instruction access error */
468 {2, SIGILL}, /* privileged instruction */
469 {3, SIGILL}, /* illegal instruction */
470 {4, SIGEMT}, /* fp disabled */
471 {36, SIGEMT}, /* cp disabled */
472 {7, SIGBUS}, /* mem address not aligned */
473 {9, SIGSEGV}, /* data access exception */
474 {10, SIGEMT}, /* tag overflow */
475 {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
476 {0, 0} /* Must be last */
477};
478
39a13178
SG
479/* Set up exception handlers for tracing and breakpoints */
480
481void
482set_debug_traps()
483{
39a13178
SG
484 struct hard_trap_info *ht;
485
39a13178 486 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
bfc55a5d 487 exceptionHandler(ht->tt, trap_low);
39a13178
SG
488
489 /* In case GDB is started before us, ack any packets (presumably
490 "$?#xx") sitting there. */
491
492 putDebugChar ('+');
493
494 initialized = 1;
495}
496
bfc55a5d
SG
497asm ("
498! Trap handler for memory errors. This just sets mem_err to be non-zero. It
499! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
500! 0 would ever contain code that could mem fault. This routine will skip
501! past the faulting instruction after setting mem_err.
502
503 .text
504 .align 4
505
506_fltr_set_mem_err:
507 sethi %hi(_mem_err), %l0
508 st %l1, [%l0 + %lo(_mem_err)]
509 jmpl %l2, %g0
510 rett %l2+4
511");
512
39a13178
SG
513static void
514set_mem_fault_trap(enable)
515 int enable;
516{
bfc55a5d 517 extern void fltr_set_mem_err();
39a13178
SG
518 mem_err = 0;
519
39a13178 520 if (enable)
bfc55a5d 521 exceptionHandler(9, fltr_set_mem_err);
39a13178 522 else
bfc55a5d 523 exceptionHandler(9, trap_low);
39a13178
SG
524}
525
526/* Convert the SPARC hardware trap type code to a unix signal number. */
4ecee2f9
SG
527
528static int
529computeSignal(tt)
530 int tt;
531{
39a13178 532 struct hard_trap_info *ht;
4ecee2f9 533
39a13178
SG
534 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
535 if (ht->tt == tt)
536 return ht->signo;
537
538 return SIGHUP; /* default for things we don't know about */
4ecee2f9
SG
539}
540
541/*
542 * While we find nice hex chars, build an int.
543 * Return number of chars processed.
544 */
545
546static int
547hexToInt(char **ptr, int *intValue)
548{
549 int numChars = 0;
550 int hexValue;
551
552 *intValue = 0;
553
554 while (**ptr)
555 {
556 hexValue = hex(**ptr);
39a13178 557 if (hexValue < 0)
4ecee2f9
SG
558 break;
559
39a13178
SG
560 *intValue = (*intValue << 4) | hexValue;
561 numChars ++;
562
ee97d673 563 (*ptr)++;
4ecee2f9
SG
564 }
565
566 return (numChars);
567}
568
569/*
570 * This function does all command procesing for interfacing to gdb. It
571 * returns 1 if you should skip the instruction at the trap address, 0
572 * otherwise.
573 */
574
bfc55a5d
SG
575extern void breakinst();
576
39a13178
SG
577static void
578handle_exception (registers)
579 unsigned long *registers;
4ecee2f9
SG
580{
581 int tt; /* Trap type */
582 int sigval;
583 int addr;
584 int length;
585 char *ptr;
39a13178 586 unsigned long *sp;
4ecee2f9
SG
587
588/* First, we must force all of the windows to be spilled out */
589
39a13178
SG
590 asm(" 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
597 save %sp, -64, %sp
4ecee2f9
SG
598 restore
599 restore
600 restore
601 restore
602 restore
603 restore
604 restore
605 restore
606");
607
bfc55a5d
SG
608 if (registers[PC] == (unsigned long)breakinst)
609 {
610 registers[PC] = registers[NPC];
611 registers[NPC] += 4;
612 }
613
39a13178 614 sp = (unsigned long *)registers[SP];
4ecee2f9
SG
615
616 tt = (registers[TBR] >> 4) & 0xff;
617
4ecee2f9
SG
618 /* reply to host that an exception has occurred */
619 sigval = computeSignal(tt);
39a13178
SG
620 ptr = remcomOutBuffer;
621
622 *ptr++ = 'T';
623 *ptr++ = hexchars[sigval >> 4];
624 *ptr++ = hexchars[sigval & 0xf];
625
626 *ptr++ = hexchars[PC >> 4];
627 *ptr++ = hexchars[PC & 0xf];
628 *ptr++ = ':';
629 ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
630 *ptr++ = ';';
631
632 *ptr++ = hexchars[FP >> 4];
633 *ptr++ = hexchars[FP & 0xf];
634 *ptr++ = ':';
635 ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
636 *ptr++ = ';';
637
638 *ptr++ = hexchars[SP >> 4];
639 *ptr++ = hexchars[SP & 0xf];
640 *ptr++ = ':';
641 ptr = mem2hex((char *)&sp, ptr, 4, 0);
642 *ptr++ = ';';
643
644 *ptr++ = hexchars[NPC >> 4];
645 *ptr++ = hexchars[NPC & 0xf];
646 *ptr++ = ':';
647 ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
648 *ptr++ = ';';
649
650 *ptr++ = hexchars[O7 >> 4];
651 *ptr++ = hexchars[O7 & 0xf];
652 *ptr++ = ':';
653 ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
654 *ptr++ = ';';
655
656 *ptr++ = 0;
4ecee2f9
SG
657
658 putpacket(remcomOutBuffer);
659
660 while (1)
661 {
4ecee2f9
SG
662 remcomOutBuffer[0] = 0;
663
664 getpacket(remcomInBuffer);
665 switch (remcomInBuffer[0])
666 {
667 case '?':
668 remcomOutBuffer[0] = 'S';
669 remcomOutBuffer[1] = hexchars[sigval >> 4];
670 remcomOutBuffer[2] = hexchars[sigval & 0xf];
671 remcomOutBuffer[3] = 0;
672 break;
673
674 case 'd':
39a13178 675 /* toggle debug flag */
4ecee2f9
SG
676 break;
677
678 case 'g': /* return the value of the CPU registers */
679 {
39a13178
SG
680 ptr = remcomOutBuffer;
681 ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
bfc55a5d 682 ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
39a13178 683 memset(ptr, '0', 32 * 8); /* Floating point */
4ecee2f9 684 mem2hex((char *)&registers[Y],
39a13178 685 ptr + 32 * 4 * 2,
4ecee2f9
SG
686 8 * 4,
687 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
688 }
689 break;
690
691 case 'G': /* set the value of the CPU registers - return OK */
692 {
bfc55a5d
SG
693 unsigned long *newsp, psr;
694
695 psr = registers[PSR];
696
39a13178
SG
697 ptr = &remcomInBuffer[1];
698 hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
bfc55a5d 699 hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
39a13178 700 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
4ecee2f9 701 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
bfc55a5d
SG
702
703 /* See if the stack pointer has moved. If so, then copy the saved
704 locals and ins to the new location. This keeps the window
705 overflow and underflow routines happy. */
706
707 newsp = (unsigned long *)registers[SP];
708 if (sp != newsp)
709 sp = memcpy(newsp, sp, 16 * 4);
710
711 /* Don't allow CWP to be modified. */
712
713 if (psr != registers[PSR])
714 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
715
4ecee2f9
SG
716 strcpy(remcomOutBuffer,"OK");
717 }
718 break;
719
720 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
39a13178 721 /* Try to read %x,%x. */
4ecee2f9
SG
722
723 ptr = &remcomInBuffer[1];
724
725 if (hexToInt(&ptr, &addr)
726 && *ptr++ == ','
727 && hexToInt(&ptr, &length))
728 {
729 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
730 break;
731
732 strcpy (remcomOutBuffer, "E03");
4ecee2f9
SG
733 }
734 else
39a13178 735 strcpy(remcomOutBuffer,"E01");
4ecee2f9
SG
736 break;
737
738 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
39a13178 739 /* Try to read '%x,%x:'. */
4ecee2f9
SG
740
741 ptr = &remcomInBuffer[1];
742
743 if (hexToInt(&ptr, &addr)
744 && *ptr++ == ','
745 && hexToInt(&ptr, &length)
746 && *ptr++ == ':')
747 {
748 if (hex2mem(ptr, (char *)addr, length, 1))
749 strcpy(remcomOutBuffer, "OK");
750 else
39a13178 751 strcpy(remcomOutBuffer, "E03");
4ecee2f9
SG
752 }
753 else
39a13178 754 strcpy(remcomOutBuffer, "E02");
4ecee2f9
SG
755 break;
756
757 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
4ecee2f9
SG
758 /* try to read optional parameter, pc unchanged if no parm */
759
760 ptr = &remcomInBuffer[1];
761 if (hexToInt(&ptr, &addr))
762 {
763 registers[PC] = addr;
764 registers[NPC] = addr + 4;
765 }
766
ee97d673
SG
767/* Need to flush the instruction cache here, as we may have deposited a
768 breakpoint, and the icache probably has no way of knowing that a data ref to
769 some location may have changed something that is in the instruction cache.
770 */
771
772 flush_i_cache();
39a13178 773 return;
4ecee2f9
SG
774
775 /* kill the program */
776 case 'k' : /* do nothing */
777 break;
bfc55a5d
SG
778#if 0
779 case 't': /* Test feature */
75a006d9 780 asm (" std %f30,[%sp]");
bfc55a5d
SG
781 break;
782#endif
783 case 'r': /* Reset */
784 asm ("call 0
785 nop ");
786 break;
787
39a13178
SG
788#if 0
789Disabled until we can unscrew this properly
4ecee2f9 790
39a13178
SG
791 case 'b': /* bBB... Set baud rate to BB... */
792 {
793 int baudrate;
794 extern void set_timer_3();
4ecee2f9 795
39a13178
SG
796 ptr = &remcomInBuffer[1];
797 if (!hexToInt(&ptr, &baudrate))
798 {
799 strcpy(remcomOutBuffer,"B01");
800 break;
801 }
4ecee2f9 802
39a13178
SG
803 /* Convert baud rate to uart clock divider */
804 switch (baudrate)
805 {
806 case 38400:
807 baudrate = 16;
808 break;
809 case 19200:
810 baudrate = 33;
811 break;
812 case 9600:
813 baudrate = 65;
814 break;
815 default:
816 strcpy(remcomOutBuffer,"B02");
817 goto x1;
818 }
4ecee2f9 819
39a13178
SG
820 putpacket("OK"); /* Ack before changing speed */
821 set_timer_3(baudrate); /* Set it */
822 }
823x1: break;
824#endif
825 } /* switch */
4ecee2f9 826
39a13178
SG
827 /* reply to the request */
828 putpacket(remcomOutBuffer);
829 }
4ecee2f9
SG
830}
831
832/* This function will generate a breakpoint exception. It is used at the
833 beginning of a program to sync up with a debugger and can be used
834 otherwise as a quick means to stop program execution and "break" into
835 the debugger. */
836
837void
838breakpoint()
839{
bfc55a5d
SG
840 if (!initialized)
841 return;
842
843 asm(" .globl _breakinst
844
845 _breakinst: ta 1
846 ");
4ecee2f9 847}
This page took 0.22715 seconds and 4 git commands to generate.