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