1 /****************************************************************************
3 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
13 ****************************************************************************/
15 /****************************************************************************
16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
18 * Module name: remcom.c $
20 * Date: 91/03/09 12:29:49 $
21 * Contributor: Lake Stevens Instrument Division$
23 * Description: low level support for gdb debugger. $
25 * Considerations: only works on target hardware $
27 * Written by: Glenn Engel $
28 * ModuleState: Experimental $
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.
36 * This code has been extensively tested on the Fujitsu SPARClite demo board.
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.
47 * The following gdb commands are supported:
49 * command function Return value
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 * P set the value of a single CPU register OK or P01 (???)
55 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
56 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
58 * c Resume at current address SNN ( signal NN)
59 * cAA..AA Continue at address AA..AA SNN
61 * s Step one instruction SNN
62 * sAA..AA Step one instruction from AA..AA SNN
66 * ? What was the last sigval ? SNN (signal NN)
68 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
71 * All commands and responses are sent with a packet which includes a
72 * checksum. A packet consists of
74 * $<packet info>#<checksum>.
77 * <packet info> :: <characters representing the command or response>
78 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
80 * When a packet is received, it is first acknowledged with either '+' or '-'.
81 * '+' indicates a successful transfer. '-' indicates a failed transfer.
86 * $m0,10#2a +$00010203040506070809101112131415#42
88 ****************************************************************************/
93 /************************************************************************
95 * external low-level support routines
98 extern void putDebugChar(); /* write a single character */
99 extern int getDebugChar(); /* read and return a single char */
101 /************************************************************************/
102 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
103 /* at least NUMREGBYTES*2 are needed for register packets */
106 static int initialized = 0; /* !0 means we've been initialized */
107 static int remote_debug = 0; /* turn on verbose debugging */
109 extern void breakinst();
111 static void hw_breakpoint();
112 static void set_mem_fault_trap();
113 static void get_in_break_mode();
114 static unsigned char *mem2hex();
116 static const char hexchars[]="0123456789abcdef";
120 static unsigned long saved_stack_pointer;
122 /* Number of bytes of registers. */
123 #define NUMREGBYTES (NUMREGS * 4)
124 enum regnames { G0, G1, G2, G3, G4, G5, G6, G7,
125 O0, O1, O2, O3, O4, O5, SP, O7,
126 L0, L1, L2, L3, L4, L5, L6, L7,
127 I0, I1, I2, I3, I4, I5, FP, I7,
129 F0, F1, F2, F3, F4, F5, F6, F7,
130 F8, F9, F10, F11, F12, F13, F14, F15,
131 F16, F17, F18, F19, F20, F21, F22, F23,
132 F24, F25, F26, F27, F28, F29, F30, F31,
134 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR,
135 CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR, UNUSED1,
137 ASR1, ASR15, ASR17, ASR18, ASR19, ASR20, ASR21, ASR22,
138 /* the following not actually implemented */
139 AWR0, AWR1, AWR2, AWR3, AWR4, AWR5, AWR6, AWR7,
140 AWR8, AWR9, AWR10, AWR11, AWR12, AWR13, AWR14, AWR15,
141 AWR16, AWR17, AWR18, AWR19, AWR20, AWR21, AWR22, AWR23,
142 AWR24, AWR25, AWR26, AWR27, AWR28, AWR29, AWR30, AWR31,
146 /*************************** ASSEMBLY CODE MACROS *************************/
149 extern void trap_low();
152 .reserve trapstack, 1000 * 4, \"bss\", 8
163 ! This function is called when any SPARC trap (except window overflow or
164 ! underflow) occurs. It makes sure that the invalid register window is still
165 ! available before jumping into C code. It will also restore the world if you
166 ! return from handle_exception.
168 ! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly.
175 srl %l3, %l0, %l4 ! wim >> cwp
176 and %l4, 0xff, %l4 ! Mask off windows 28, 29
178 bne window_fine ! Branch if not in the invalid window
181 ! Handle window overflow
183 mov %g1, %l4 ! Save g1, we use it to hold the wim
184 srl %l3, 1, %g1 ! Rotate wim right
185 and %g1, 0xff, %g1 ! Mask off windows 28, 29
187 bg good_wim ! Branch if new wim is non-zero
190 ! At this point, we need to bring a 1 into the high order bit of the wim.
191 ! Since we don't want to make any assumptions about the number of register
192 ! windows, we figure it out dynamically so as to setup the wim correctly.
194 ! The normal way doesn't work on the sparclet as register windows
195 ! 28 and 29 are special purpose windows.
196 !not %g1 ! Fill g1 with ones
197 !mov %g1, %wim ! Fill the wim with ones
201 !mov %wim, %g1 ! Read back the wim
202 !inc %g1 ! Now g1 has 1 just to left of wim
203 !srl %g1, 1, %g1 ! Now put 1 at top of wim
205 mov 0x80, %g1 ! Hack for sparclet
207 ! This doesn't work on the sparclet.
208 !mov %g0, %wim ! Clear wim so that subsequent save
210 andn %l3, 0xff, %l5 ! Clear wim but not windows 28, 29
217 save %g0, %g0, %g0 ! Slip into next window
218 mov %g1, %wim ! Install the new wim
220 std %l0, [%sp + 0 * 4] ! save L & I registers
221 std %l2, [%sp + 2 * 4]
222 std %l4, [%sp + 4 * 4]
223 std %l6, [%sp + 6 * 4]
225 std %i0, [%sp + 8 * 4]
226 std %i2, [%sp + 10 * 4]
227 std %i4, [%sp + 12 * 4]
228 std %i6, [%sp + 14 * 4]
230 restore ! Go back to trap window.
231 mov %l4, %g1 ! Restore %g1
234 sethi %hi(in_trap_handler), %l4
235 ld [%lo(in_trap_handler) + %l4], %l5
240 set trapstack+1000*4, %sp ! Switch to trap stack
243 st %l5, [%lo(in_trap_handler) + %l4]
244 sub %sp,(16+1+6+1+88)*4,%sp ! Make room for input & locals
245 ! + hidden arg + arg spill
246 ! + doubleword alignment
249 std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
250 std %g2, [%sp + (24 + 2) * 4]
251 std %g4, [%sp + (24 + 4) * 4]
252 std %g6, [%sp + (24 + 6) * 4]
254 std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
255 std %i2, [%sp + (24 + 10) * 4]
256 std %i4, [%sp + (24 + 12) * 4]
257 std %i6, [%sp + (24 + 14) * 4]
259 ! FP regs (sparclet doesn't have fpu)
263 st %l4, [%sp + (24 + 64) * 4] ! Y
264 st %l0, [%sp + (24 + 65) * 4] ! PSR
265 st %l3, [%sp + (24 + 66) * 4] ! WIM
266 st %l5, [%sp + (24 + 67) * 4] ! TBR
267 st %l1, [%sp + (24 + 68) * 4] ! PC
268 st %l2, [%sp + (24 + 69) * 4] ! NPC
269 ! CPSR and FPSR not impl
271 mov %l4, %psr ! Turn on traps, disable interrupts
276 ! Save coprocessor state.
277 ! See SK/demo/hdlc_demo/ldc_swap_context.S.
280 sethi %hi(0x2000), %l5 ! EC bit in PSR
282 mov %l5, %psr ! enable coprocessor
283 nop ! 3 nops after write to %psr (needed?)
286 crdcxt %ccsr, %l1 ! capture CCSR
288 cwrcxt %l2, %ccsr ! set CCP state machine for CCFR
289 crdcxt %ccfr, %l2 ! capture CCOR
290 cwrcxt %l2, %ccfr ! tickle CCFR
291 crdcxt %ccfr, %l3 ! capture CCOBR
292 cwrcxt %l3, %ccfr ! tickle CCFR
293 crdcxt %ccfr, %l4 ! capture CCIBR
294 cwrcxt %l4, %ccfr ! tickle CCFR
295 crdcxt %ccfr, %l5 ! capture CCIR
296 cwrcxt %l5, %ccfr ! tickle CCFR
297 crdcxt %ccpr, %l6 ! capture CCPR
298 crdcxt %cccrcr, %l7 ! capture CCCRCR
299 st %l1, [%sp + (24 + 72) * 4] ! save CCSR
300 st %l2, [%sp + (24 + 75) * 4] ! save CCOR
301 st %l3, [%sp + (24 + 76) * 4] ! save CCOBR
302 st %l4, [%sp + (24 + 77) * 4] ! save CCIBR
303 st %l5, [%sp + (24 + 78) * 4] ! save CCIR
304 st %l6, [%sp + (24 + 73) * 4] ! save CCPR
305 st %l7, [%sp + (24 + 74) * 4] ! save CCCRCR
306 mov %l0, %psr ! restore original PSR
307 nop ! 3 nops after write to %psr (needed?)
311 ! End of saving coprocessor state.
314 ! Part of this is silly -- we should not display ASR15 or ASR19 at all.
316 sethi %hi(0x01000000), %l6
317 st %l6, [%sp + (24 + 81) * 4] ! ASR15 == NOP
318 sethi %hi(0xdeadc0de), %l6
319 or %l6, %lo(0xdeadc0de), %l6
320 st %l6, [%sp + (24 + 84) * 4] ! ASR19 == DEADC0DE
323 st %l4, [%sp + (24 + 80) * 4]
324 ! rd %asr15, %l4 ! must not read ASR15
325 ! st %l4, [%sp + (24 + 81) * 4] ! (illegal instr trap)
327 st %l4, [%sp + (24 + 82) * 4]
329 st %l4, [%sp + (24 + 83) * 4]
330 ! rd %asr19, %l4 ! must not read asr19
331 ! st %l4, [%sp + (24 + 84) * 4] ! (halts the CPU)
333 st %l4, [%sp + (24 + 85) * 4]
335 st %l4, [%sp + (24 + 86) * 4]
337 st %l4, [%sp + (24 + 87) * 4]
339 ! End of saving asr regs
341 call _handle_exception
342 add %sp, 24 * 4, %o0 ! Pass address of registers
344 ! Reload all of the registers that aren't on the stack
346 ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
347 ldd [%sp + (24 + 2) * 4], %g2
348 ldd [%sp + (24 + 4) * 4], %g4
349 ldd [%sp + (24 + 6) * 4], %g6
351 ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
352 ldd [%sp + (24 + 10) * 4], %i2
353 ldd [%sp + (24 + 12) * 4], %i4
354 ldd [%sp + (24 + 14) * 4], %i6
356 ! FP regs (sparclet doesn't have fpu)
358 ! Update the coprocessor registers.
359 ! See SK/demo/hdlc_demo/ldc_swap_context.S.
362 sethi %hi(0x2000), %l5 ! EC bit in PSR
364 mov %l5, %psr ! enable coprocessor
365 nop ! 3 nops after write to %psr (needed?)
370 cwrcxt %l2, %ccsr ! set CCP state machine for CCFR
372 ld [%sp + (24 + 72) * 4], %l1 ! saved CCSR
373 ld [%sp + (24 + 75) * 4], %l2 ! saved CCOR
374 ld [%sp + (24 + 76) * 4], %l3 ! saved CCOBR
375 ld [%sp + (24 + 77) * 4], %l4 ! saved CCIBR
376 ld [%sp + (24 + 78) * 4], %l5 ! saved CCIR
377 ld [%sp + (24 + 73) * 4], %l6 ! saved CCPR
378 ld [%sp + (24 + 74) * 4], %l7 ! saved CCCRCR
380 cwrcxt %l2, %ccfr ! restore CCOR
381 cwrcxt %l3, %ccfr ! restore CCOBR
382 cwrcxt %l4, %ccfr ! restore CCIBR
383 cwrcxt %l5, %ccfr ! restore CCIR
384 cwrcxt %l6, %ccpr ! restore CCPR
385 cwrcxt %l7, %cccrcr ! restore CCCRCR
386 cwrcxt %l1, %ccsr ! restore CCSR
388 mov %l0, %psr ! restore PSR
389 nop ! 3 nops after write to %psr (needed?)
393 ! End of coprocessor handling stuff.
396 ld [%sp + (24 + 80) * 4], %l4
398 ! ld [%sp + (24 + 81) * 4], %l4 ! can't write asr15
400 ld [%sp + (24 + 82) * 4], %l4
402 ld [%sp + (24 + 83) * 4], %l4
404 ! ld [%sp + (24 + 84) * 4], %l4 ! can't write asr19
406 ! ld [%sp + (24 + 85) * 4], %l4 ! can't write asr20
408 ! ld [%sp + (24 + 86) * 4], %l4 ! can't write asr21
410 ld [%sp + (24 + 87) * 4], %l4
413 ! End of restoring asr regs
416 ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
417 ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
419 restore ! Ensure that previous window is valid
420 save %g0, %g0, %g0 ! by causing a window_underflow trap
423 mov %l1, %psr ! Make sure that traps are disabled
425 nop ! 3 nops after write to %psr (needed?)
429 sethi %hi(in_trap_handler), %l4
430 ld [%lo(in_trap_handler) + %l4], %l5
432 st %l5, [%lo(in_trap_handler) + %l4]
434 jmpl %l2, %g0 ! Restore old PC
435 rett %l3 ! Restore old nPC
438 /* Convert ch from a hex digit to an int */
444 if (ch >= 'a' && ch <= 'f')
446 if (ch >= '0' && ch <= '9')
448 if (ch >= 'A' && ch <= 'F')
453 /* scan for the sequence $<data>#<checksum> */
457 unsigned char *buffer;
459 unsigned char checksum;
460 unsigned char xmitcsum;
466 /* wait around for the start character, ignore all other characters */
467 while ((ch = getDebugChar ()) != '$')
475 /* now, read until a # or end of buffer is found */
476 while (count < BUFMAX)
478 ch = getDebugChar ();
483 checksum = checksum + ch;
491 ch = getDebugChar ();
492 xmitcsum = hex (ch) << 4;
493 ch = getDebugChar ();
494 xmitcsum += hex (ch);
496 if (checksum != xmitcsum)
498 putDebugChar ('-'); /* failed checksum */
502 putDebugChar ('+'); /* successful transfer */
504 /* if a sequence char is present, reply the sequence ID */
505 if (buffer[2] == ':')
507 putDebugChar (buffer[0]);
508 putDebugChar (buffer[1]);
519 /* send the packet in buffer. */
523 unsigned char *buffer;
525 unsigned char checksum;
529 /* $<packet info>#<checksum>. */
536 while (ch = buffer[count])
544 putDebugChar(hexchars[checksum >> 4]);
545 putDebugChar(hexchars[checksum & 0xf]);
548 while (getDebugChar() != '+');
551 static char remcomInBuffer[BUFMAX];
552 static char remcomOutBuffer[BUFMAX];
554 /* Indicate to caller of mem2hex or hex2mem that there has been an
556 static volatile int mem_err = 0;
558 /* Convert the memory pointed to by mem into hex, placing result in buf.
559 * Return a pointer to the last char put in buf (null), in case of mem fault,
561 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
562 * a 0, else treat a fault like any other fault in the stub.
565 static unsigned char *
566 mem2hex(mem, buf, count, may_fault)
574 set_mem_fault_trap(may_fault);
581 *buf++ = hexchars[ch >> 4];
582 *buf++ = hexchars[ch & 0xf];
587 set_mem_fault_trap(0);
592 /* convert the hex array pointed to by buf into binary to be placed in mem
593 * return a pointer to the character AFTER the last byte written */
596 hex2mem(buf, mem, count, may_fault)
605 set_mem_fault_trap(may_fault);
607 for (i=0; i<count; i++)
609 ch = hex(*buf++) << 4;
616 set_mem_fault_trap(0);
621 /* This table contains the mapping between SPARC hardware trap types, and
622 signals, which are primarily what GDB understands. It also indicates
623 which hardware traps we need to commandeer when initializing the stub. */
625 static struct hard_trap_info
627 unsigned char tt; /* Trap type code for SPARClite */
628 unsigned char signo; /* Signal that we map this trap into */
629 } hard_trap_info[] = {
630 {1, SIGSEGV}, /* instruction access exception */
631 {0x3b, SIGSEGV}, /* instruction access error */
632 {2, SIGILL}, /* illegal instruction */
633 {3, SIGILL}, /* privileged instruction */
634 {4, SIGEMT}, /* fp disabled */
635 {0x24, SIGEMT}, /* cp disabled */
636 {7, SIGBUS}, /* mem address not aligned */
637 {0x29, SIGSEGV}, /* data access exception */
638 {10, SIGEMT}, /* tag overflow */
639 {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
640 {0, 0} /* Must be last */
643 /* Set up exception handlers for tracing and breakpoints */
648 struct hard_trap_info *ht;
650 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
651 exceptionHandler(ht->tt, trap_low);
657 ! Trap handler for memory errors. This just sets mem_err to be non-zero. It
658 ! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
659 ! 0 would ever contain code that could mem fault. This routine will skip
660 ! past the faulting instruction after setting mem_err.
666 sethi %hi(_mem_err), %l0
667 st %l1, [%l0 + %lo(_mem_err)]
673 set_mem_fault_trap(enable)
676 extern void fltr_set_mem_err();
680 exceptionHandler(0x29, fltr_set_mem_err);
682 exceptionHandler(0x29, trap_low);
689 _dummy_hw_breakpoint:
697 set_hw_breakpoint_trap(enable)
700 extern void dummy_hw_breakpoint();
703 exceptionHandler(255, dummy_hw_breakpoint);
705 exceptionHandler(255, trap_low);
713 mesg("get_in_break_mode, sp = ");
716 set_hw_breakpoint_trap(1);
719 sethi %hi(0xff10), %l4
720 or %l4, %lo(0xff10), %l4
727 set_hw_breakpoint_trap(0);
730 /* Convert the SPARC hardware trap type code to a unix signal number. */
736 struct hard_trap_info *ht;
738 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
742 return SIGHUP; /* default for things we don't know about */
746 * While we find nice hex chars, build an int.
747 * Return number of chars processed.
751 hexToInt(char **ptr, int *intValue)
760 hexValue = hex(**ptr);
764 *intValue = (*intValue << 4) | hexValue;
774 * This function does all command procesing for interfacing to gdb. It
775 * returns 1 if you should skip the instruction at the trap address, 0
780 handle_exception (registers)
781 unsigned long *registers;
783 int tt; /* Trap type */
791 /* First, we must force all of the windows to be spilled out */
794 ! Ugh. sparclet has broken save
829 if (registers[PC] == (unsigned long)breakinst)
831 registers[PC] = registers[NPC];
834 sp = (unsigned long *)registers[SP];
836 tt = (registers[TBR] >> 4) & 0xff;
838 /* reply to host that an exception has occurred */
839 sigval = computeSignal(tt);
840 ptr = remcomOutBuffer;
843 *ptr++ = hexchars[sigval >> 4];
844 *ptr++ = hexchars[sigval & 0xf];
846 *ptr++ = hexchars[PC >> 4];
847 *ptr++ = hexchars[PC & 0xf];
849 ptr = mem2hex((char *)®isters[PC], ptr, 4, 0);
852 *ptr++ = hexchars[FP >> 4];
853 *ptr++ = hexchars[FP & 0xf];
855 ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
858 *ptr++ = hexchars[SP >> 4];
859 *ptr++ = hexchars[SP & 0xf];
861 ptr = mem2hex((char *)&sp, ptr, 4, 0);
864 *ptr++ = hexchars[NPC >> 4];
865 *ptr++ = hexchars[NPC & 0xf];
867 ptr = mem2hex((char *)®isters[NPC], ptr, 4, 0);
870 *ptr++ = hexchars[O7 >> 4];
871 *ptr++ = hexchars[O7 & 0xf];
873 ptr = mem2hex((char *)®isters[O7], ptr, 4, 0);
878 putpacket(remcomOutBuffer);
882 remcomOutBuffer[0] = 0;
884 ptr = getpacket(remcomInBuffer);
888 remcomOutBuffer[0] = 'S';
889 remcomOutBuffer[1] = hexchars[sigval >> 4];
890 remcomOutBuffer[2] = hexchars[sigval & 0xf];
891 remcomOutBuffer[3] = 0;
895 remote_debug = !(remote_debug); /* toggle debug flag */
898 case 'g': /* return the value of the CPU registers */
900 ptr = remcomOutBuffer;
901 ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
902 ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
903 memset(ptr, '0', 32 * 8); /* Floating point */
904 ptr = mem2hex((char *)®isters[Y],
907 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
908 ptr = mem2hex((char *)®isters[CCSR],
911 0); /* CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR */
912 ptr = mem2hex((char *)®isters[ASR1],
915 0); /* ASR1,ASR15,ASR17,ASR18,ASR19,ASR20,ASR21,ASR22 */
916 #if 0 /* not implemented */
917 ptr = mem2hex((char *) ®isters[AWR0],
920 0); /* Alternate Window Registers */
925 case 'G': /* set value of all the CPU registers - return OK */
926 case 'P': /* set value of one CPU register - return OK */
928 unsigned long *newsp, psr;
930 psr = registers[PSR];
932 if (ptr[-1] == 'P') /* do a single register */
936 if (hexToInt (&ptr, ®no)
938 if (regno >= L0 && regno <= I7)
939 hex2mem (ptr, sp + regno - L0, 4, 0);
941 hex2mem (ptr, (char *)®isters[regno], 4, 0);
944 strcpy (remcomOutBuffer, "P01");
950 hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
951 hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
952 hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y],
953 8 * 4, 0); /* Y,PSR,WIM,TBR,PC,NPC,FPSR,CPSR */
954 hex2mem(ptr + 72 * 4 * 2, (char *)®isters[CCSR],
955 8 * 4, 0); /* CCSR,CCPR,CCCRCR,CCOR,CCOBR,CCIBR,CCIR */
956 hex2mem(ptr + 80 * 4 * 2, (char *)®isters[ASR1],
957 8 * 4, 0); /* ASR1 ... ASR22 */
958 #if 0 /* not implemented */
959 hex2mem(ptr + 88 * 4 * 2, (char *)®isters[AWR0],
960 8 * 4, 0); /* Alternate Window Registers */
963 /* See if the stack pointer has moved. If so, then copy the saved
964 locals and ins to the new location. This keeps the window
965 overflow and underflow routines happy. */
967 newsp = (unsigned long *)registers[SP];
969 sp = memcpy(newsp, sp, 16 * 4);
971 /* Don't allow CWP to be modified. */
973 if (psr != registers[PSR])
974 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
976 strcpy(remcomOutBuffer,"OK");
980 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
981 /* Try to read %x,%x. */
983 if (hexToInt(&ptr, &addr)
985 && hexToInt(&ptr, &length))
987 if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
990 strcpy (remcomOutBuffer, "E03");
993 strcpy(remcomOutBuffer,"E01");
996 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
997 /* Try to read '%x,%x:'. */
999 if (hexToInt(&ptr, &addr)
1001 && hexToInt(&ptr, &length)
1004 if (hex2mem(ptr, (char *)addr, length, 1))
1005 strcpy(remcomOutBuffer, "OK");
1007 strcpy(remcomOutBuffer, "E03");
1010 strcpy(remcomOutBuffer, "E02");
1013 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
1014 /* try to read optional parameter, pc unchanged if no parm */
1016 if (hexToInt(&ptr, &addr))
1018 registers[PC] = addr;
1019 registers[NPC] = addr + 4;
1022 /* Need to flush the instruction cache here, as we may have deposited a
1023 breakpoint, and the icache probably has no way of knowing that a data ref to
1024 some location may have changed something that is in the instruction cache.
1030 /* kill the program */
1031 case 'k' : /* do nothing */
1034 case 't': /* Test feature */
1035 asm (" std %f30,[%sp]");
1038 case 'r': /* Reset */
1044 Disabled until we can unscrew this properly
1046 case 'b': /* bBB... Set baud rate to BB... */
1049 extern void set_timer_3();
1051 if (!hexToInt(&ptr, &baudrate))
1053 strcpy(remcomOutBuffer,"B01");
1057 /* Convert baud rate to uart clock divider */
1070 strcpy(remcomOutBuffer,"B02");
1074 putpacket("OK"); /* Ack before changing speed */
1075 set_timer_3(baudrate); /* Set it */
1081 /* reply to the request */
1082 putpacket(remcomOutBuffer);
1086 /* This function will generate a breakpoint exception. It is used at the
1087 beginning of a program to sync up with a debugger and can be used
1088 otherwise as a quick means to stop program execution and "break" into
1097 asm(" .globl _breakinst
1111 #if 0 /* experimental and never finished, left here for reference */
1115 asm(" sub %sp,(16+1+6+1+121)*4,%sp ! Make room for input & locals
1116 ! + hidden arg + arg spill
1117 ! + doubleword alignment
1120 ! Leave a trail of breadcrumbs! (save register save area for debugging)
1123 sethi %hi(_debug_registers), %l1
1124 st %l0, [%lo(_debug_registers) + %l1]
1126 ! Save the Alternate Register Set: (not implemented yet)
1127 ! To save the Alternate Register set, we must:
1128 ! 1) Save the current SP in some global location.
1129 ! 2) Swap the register sets.
1130 ! 3) Save the Alternate SP in the Y register
1131 ! 4) Fetch the SP that we saved in step 1.
1132 ! 5) Use that to save the rest of the regs (not forgetting ASP in Y)
1133 ! 6) Restore the Alternate SP from Y
1134 ! 7) Swap the registers back.
1136 ! 1) Copy the current stack pointer to global _SAVED_STACK_POINTER:
1137 sethi %hi(_saved_stack_pointer), %l0
1138 st %sp, [%lo(_saved_stack_pointer) + %l0]
1140 ! 2) Swap the register sets:
1142 sethi %hi(0x10000), %l2
1145 nop ! 3 nops after write to %psr (needed?)
1149 ! 3) Save Alternate L0 in Y
1152 ! 4) Load former SP into alternate SP, using L0
1153 sethi %hi(_saved_stack_pointer), %l0
1154 or %lo(_saved_stack_pointer), %l0, %l0
1157 ! 4.5) Restore alternate L0
1160 ! 5) Save the Alternate Window Registers
1161 st %r0, [%sp + (24 + 88) * 4] ! AWR0
1162 st %r1, [%sp + (24 + 89) * 4] ! AWR1
1163 st %r2, [%sp + (24 + 90) * 4] ! AWR2
1164 st %r3, [%sp + (24 + 91) * 4] ! AWR3
1165 st %r4, [%sp + (24 + 92) * 4] ! AWR4
1166 st %r5, [%sp + (24 + 93) * 4] ! AWR5
1167 st %r6, [%sp + (24 + 94) * 4] ! AWR6
1168 st %r7, [%sp + (24 + 95) * 4] ! AWR7
1169 st %r8, [%sp + (24 + 96) * 4] ! AWR8
1170 st %r9, [%sp + (24 + 97) * 4] ! AWR9
1171 st %r10, [%sp + (24 + 98) * 4] ! AWR10
1172 st %r11, [%sp + (24 + 99) * 4] ! AWR11
1173 st %r12, [%sp + (24 + 100) * 4] ! AWR12
1174 st %r13, [%sp + (24 + 101) * 4] ! AWR13
1175 ! st %r14, [%sp + (24 + 102) * 4] ! AWR14 (SP)
1176 st %r15, [%sp + (24 + 103) * 4] ! AWR15
1177 st %r16, [%sp + (24 + 104) * 4] ! AWR16
1178 st %r17, [%sp + (24 + 105) * 4] ! AWR17
1179 st %r18, [%sp + (24 + 106) * 4] ! AWR18
1180 st %r19, [%sp + (24 + 107) * 4] ! AWR19
1181 st %r20, [%sp + (24 + 108) * 4] ! AWR20
1182 st %r21, [%sp + (24 + 109) * 4] ! AWR21
1183 st %r22, [%sp + (24 + 110) * 4] ! AWR22
1184 st %r23, [%sp + (24 + 111) * 4] ! AWR23
1185 st %r24, [%sp + (24 + 112) * 4] ! AWR24
1186 st %r25, [%sp + (24 + 113) * 4] ! AWR25
1187 st %r26, [%sp + (24 + 114) * 4] ! AWR26
1188 st %r27, [%sp + (24 + 115) * 4] ! AWR27
1189 st %r28, [%sp + (24 + 116) * 4] ! AWR28
1190 st %r29, [%sp + (24 + 117) * 4] ! AWR29
1191 st %r30, [%sp + (24 + 118) * 4] ! AWR30
1192 st %r31, [%sp + (24 + 119) * 4] ! AWR21
1194 ! Get the Alternate PSR (I hope...)
1197 st %l2, [%sp + (24 + 120) * 4] ! APSR
1199 ! Don't forget the alternate stack pointer
1202 st %l3, [%sp + (24 + 102) * 4] ! AWR14 (SP)
1204 ! 6) Restore the Alternate SP (saved in Y)
1209 ! 7) Swap the registers back:
1212 sethi %hi(0x10000), %l2
1215 nop ! 3 nops after write to %psr (needed?)