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